| title | Smart Contract Interaction |
|---|---|
| description | Integrate with Paycrest using the Gateway smart contract for onchain order management. |
Interact directly with the Paycrest Gateway smart contract for onchain stablecoin-to-fiat (offramp) order creation, settlement, and refunds. This approach gives you full control over the blockchain transactions and is ideal for dapps, wallets, or any EVM-compatible application.
This guide uses **Viem** for smart contract interactions, which is the recommended Ethereum library for modern applications. Viem provides better TypeScript support, improved performance, and a more intuitive API compared to ethers.js.The Gateway contract is a multi-chain EVM-based smart contract that facilitates the on-chain lifecycle of payment orders. It empowers users to create off-ramp orders while enabling liquidity providers to facilitate those orders at competitive exchange rates.
- Ethereum Provider: MetaMask, WalletConnect, or any Web3 provider
- Viem: For smart contract interactions
- USDT/USDC Balance: Sufficient token balance for orders
- Gas Fees: ETH for transaction fees
// Connect to user's wallet const publicClient = createPublicClient({ chain: base, transport: http() });
const walletClient = await createWalletClient({ chain: base, transport: window.ethereum });
const [userAddress] = await walletClient.getAddresses();
</Tab>
<Tab title="Python">
```python
from web3 import Web3
from eth_account import Account
# Connect to Base network
w3 = Web3(Web3.HTTPProvider('https://mainnet.base.org'))
# For browser integration, you'd typically use a wallet like MetaMask
# This example shows how to connect with a private key
account = Account.from_key('YOUR_PRIVATE_KEY')
user_address = account.address
import ( "fmt" "log"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)
func connectWallet() { // Connect to Base network client, err := ethclient.Dial("https://mainnet.base.org") if err != nil { log.Fatal(err) }
// Load private key
privateKey, err := crypto.HexToECDSA("YOUR_PRIVATE_KEY")
if err != nil {
log.Fatal(err)
}
// Get account address
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*crypto.PublicKey)
if !ok {
log.Fatal("error casting public key to ECDSA")
}
userAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
fmt.Printf("Connected wallet: %s\n", userAddress.Hex())
}
</Tab>
<Tab title="cURL">
```bash
# Wallet connection is typically done in your application code
# rather than with cURL. Use one of the programming language examples above.
// Gateway contract configuration const GATEWAY_ADDRESS = "0xE8bc3B607CfE68F47000E3d200310D49041148Fc"; const USDT_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7";
// Contract instances const gateway = getContract({ address: GATEWAY_ADDRESS, abi: GATEWAY_ABI, publicClient, walletClient });
const usdt = getContract({ address: USDT_ADDRESS, abi: USDT_ABI, publicClient, walletClient });
</Tab>
<Tab title="Python">
```python
from web3 import Web3
# Gateway contract configuration
GATEWAY_ADDRESS = "0xE8bc3B607CfE68F47000E3d200310D49041148Fc"
USDT_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7"
# Contract instances
gateway = w3.eth.contract(address=GATEWAY_ADDRESS, abi=GATEWAY_ABI)
usdt = w3.eth.contract(address=USDT_ADDRESS, abi=USDT_ABI)
import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" )
// Gateway contract configuration const GATEWAY_ADDRESS = "0xE8bc3B607CfE68F47000E3d200310D49041148Fc" const USDT_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7"
func initializeContracts(client *ethclient.Client) { gatewayAddress := common.HexToAddress(GATEWAY_ADDRESS) usdtAddress := common.HexToAddress(USDT_ADDRESS)
// Contract instances would be created with ABI bindings
// This is a simplified example
fmt.Printf("Gateway contract: %s\n", gatewayAddress.Hex())
fmt.Printf("USDT contract: %s\n", usdtAddress.Hex())
}
</Tab>
<Tab title="cURL">
```bash
# Contract initialization is typically done in your application code
# rather than with cURL. Use one of the programming language examples above.
const hash = await walletClient.writeContract(request);
const receipt = await publicClient.waitForTransactionReceipt({ hash });
const orderId = extractOrderId(receipt);
return { orderId, transactionHash: receipt.hash };
} catch (error) { console.error("Error creating order:", error); throw error; } }
</Tab>
<Tab title="Python">
```python
async def create_off_ramp_order(amount, recipient, refund_address):
try:
rate = await get_exchange_rate()
account_name = await verify_account(recipient)
message_hash = await encrypt_recipient_data({**recipient, 'accountName': account_name})
await approve_usdt(amount)
# Build transaction
tx = gateway.functions.createOrder(
USDT_ADDRESS,
w3.to_wei(amount, 'ether'),
rate,
'0x0000000000000000000000000000000000000000',
0,
refund_address,
message_hash
).build_transaction({
'from': user_address,
'gas': 200000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(user_address)
})
# Sign and send transaction
signed_tx = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
order_id = extract_order_id(receipt)
return {'orderId': order_id, 'transactionHash': receipt['transactionHash'].hex()}
except Exception as error:
print(f"Error creating order: {error}")
raise error
accountName, err := verifyAccount(recipient)
if err != nil {
return err
}
messageHash, err := encryptRecipientData(recipient, accountName)
if err != nil {
return err
}
err = approveUSDT(amount)
if err != nil {
return err
}
// Build transaction data
data := buildCreateOrderData(amount, rate, refundAddress, messageHash)
// Create transaction
tx := &types.Transaction{
To: &gatewayAddress,
Value: big.NewInt(0),
Gas: 200000,
GasPrice: big.NewInt(20000000000), // 20 gwei
Data: data,
}
// Sign and send transaction
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(8453)), privateKey)
if err != nil {
return err
}
err = client.SendTransaction(context.Background(), signedTx)
if err != nil {
return err
}
fmt.Printf("Order created with hash: %s\n", signedTx.Hash().Hex())
return nil
}
</Tab>
<Tab title="cURL">
```bash
# Smart contract interactions are typically done in your application code
# rather than with cURL. Use one of the programming language examples above.
async function verifyAccount(recipient) { const response = await fetch("https://api.paycrest.io/v1/verify-account", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ institution: recipient.institution, accountIdentifier: recipient.accountIdentifier }) }); const data = await response.json(); return data.data; }
</Tab>
<Tab title="Python">
```python
import requests
async def get_exchange_rate():
response = requests.get("https://api.paycrest.io/v1/rates/usdt/1/ngn")
data = response.json()
return float(data['data'])
async def verify_account(recipient):
response = requests.post(
"https://api.paycrest.io/v1/verify-account",
headers={"Content-Type": "application/json"},
json={
"institution": recipient["institution"],
"accountIdentifier": recipient["accountIdentifier"]
}
)
data = response.json()
return data['data']
func getExchangeRate() (float64, error) { resp, err := http.Get("https://api.paycrest.io/v1/rates/usdt/1/ngn") if err != nil { return 0, err } defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return 0, err
}
var result map[string]interface{}
json.Unmarshal(body, &result)
rateStr := result["data"].(string)
rate, err := strconv.ParseFloat(rateStr, 64)
if err != nil {
return 0, err
}
return rate, nil
}
func verifyAccount(recipient map[string]interface{}) (string, error) { jsonData, _ := json.Marshal(map[string]interface{}{ "institution": recipient["institution"], "accountIdentifier": recipient["accountIdentifier"], })
resp, err := http.Post(
"https://api.paycrest.io/v1/verify-account",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var result map[string]interface{}
json.Unmarshal(body, &result)
return result["data"].(string), nil
}
</Tab>
<Tab title="cURL">
```bash
# Get exchange rate
curl -X GET "https://api.paycrest.io/v1/rates/usdt/1/ngn"
# Verify account
curl -X POST "https://api.paycrest.io/v1/verify-account" \
-H "Content-Type: application/json" \
-d '{
"institution": "GTB",
"accountIdentifier": "1234567890"
}'
async def encrypt_recipient_data(recipient): response = requests.get("https://api.paycrest.io/v1/pubkey") public_key = response.json()['data']
# Import public key
key = RSA.import_key(public_key)
cipher = PKCS1_OAEP.new(key)
# Encrypt recipient data
recipient_json = json.dumps(recipient)
encrypted = cipher.encrypt(recipient_json.encode('utf-8'))
encrypted_b64 = base64.b64encode(encrypted).decode('utf-8')
return encrypted_b64
</Tab>
<Tab title="Go">
```go
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"
)
func encryptRecipientData(recipient map[string]interface{}) (string, error) {
// Get public key
resp, err := http.Get("https://api.paycrest.io/v1/pubkey")
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var result map[string]interface{}
json.Unmarshal(body, &result)
publicKeyPEM := result["data"].(string)
// Parse public key
block, _ := pem.Decode([]byte(publicKeyPEM))
if block == nil {
return "", fmt.Errorf("failed to parse public key")
}
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return "", err
}
rsaPubKey, ok := pubKey.(*rsa.PublicKey)
if !ok {
return "", fmt.Errorf("not an RSA public key")
}
// Encrypt recipient data
recipientJSON, _ := json.Marshal(recipient)
encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPubKey, recipientJSON)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(encrypted), nil
}
</Tab>
</Tabs>
## Token Approval
<Tabs>
<Tab title="JavaScript">
```javascript
async function approveUSDT(amount) {
const usdtAmount = parseUnits(amount, 6);
const allowance = await usdt.read.allowance([userAddress, GATEWAY_ADDRESS]);
if (allowance < usdtAmount) {
const { request } = await usdt.simulate.approve({
args: [GATEWAY_ADDRESS, usdtAmount]
});
const hash = await walletClient.writeContract(request);
await publicClient.waitForTransactionReceipt({ hash });
}
}
if allowance < usdt_amount:
tx = usdt.functions.approve(
GATEWAY_ADDRESS,
usdt_amount
).build_transaction({
'from': user_address,
'gas': 100000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(user_address)
})
signed_tx = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
w3.eth.wait_for_transaction_receipt(tx_hash)
</Tab>
<Tab title="Go">
```go
func approveUSDT(amount string) error {
usdtAmount := new(big.Int)
usdtAmount.SetString(amount, 10)
usdtAmount.Mul(usdtAmount, new(big.Int).Exp(big.NewInt(10), big.NewInt(6), nil)) // USDT has 6 decimals
// Check current allowance
allowance, err := usdtContract.Allowance(nil, userAddress, gatewayAddress)
if err != nil {
return err
}
if allowance.Cmp(usdtAmount) < 0 {
// Build approve transaction
data := buildApproveData(gatewayAddress, usdtAmount)
tx := &types.Transaction{
To: &usdtAddress,
Value: big.NewInt(0),
Gas: 100000,
GasPrice: big.NewInt(20000000000), // 20 gwei
Data: data,
}
// Sign and send transaction
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(8453)), privateKey)
if err != nil {
return err
}
err = client.SendTransaction(context.Background(), signedTx)
if err != nil {
return err
}
fmt.Printf("USDT approved with hash: %s\n", signedTx.Hash().Hex())
}
return nil
}
amount := new(big.Float).Quo(
new(big.Float).SetInt(orderInfo.Amount),
new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(6), nil)),
)
return map[string]interface{}{
"sender": orderInfo.Sender.Hex(),
"token": orderInfo.Token.Hex(),
"amount": amount.Text('f', 6),
"isFulfilled": orderInfo.IsFulfilled,
"isRefunded": orderInfo.IsRefunded,
"refundAddress": orderInfo.RefundAddress.Hex(),
}, nil
}
</Tab>
<Tab title="cURL">
```bash
# Get order information from blockchain
# This requires a Web3 provider and contract interaction
# Use one of the programming language examples above.
const unwatchOrderSettled = publicClient.watchContractEvent({ address: GATEWAY_ADDRESS, abi: GATEWAY_ABI, eventName: 'OrderSettled', onLogs: (logs) => { logs.forEach((log) => { console.log("Order Settled:", { orderId: log.args.orderId, liquidityProvider: log.args.liquidityProvider, settlePercent: log.args.settlePercent }); }); } });
const unwatchOrderRefunded = publicClient.watchContractEvent({ address: GATEWAY_ADDRESS, abi: GATEWAY_ABI, eventName: 'OrderRefunded', onLogs: (logs) => { logs.forEach((log) => { console.log("Order Refunded:", { fee: formatUnits(log.args.fee, 6), orderId: log.args.orderId }); }); } });
</Tab>
<Tab title="Python">
```python
from web3.middleware import geth_poa_middleware
import asyncio
# Add middleware for Base network
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
def handle_order_created(event):
print("Order Created:", {
'sender': event['args']['sender'],
'token': event['args']['token'],
'amount': w3.from_wei(event['args']['amount'], 'ether'),
'orderId': event['args']['orderId'],
'rate': event['args']['rate']
})
def handle_order_settled(event):
print("Order Settled:", {
'orderId': event['args']['orderId'],
'liquidityProvider': event['args']['liquidityProvider'],
'settlePercent': event['args']['settlePercent']
})
def handle_order_refunded(event):
print("Order Refunded:", {
'fee': w3.from_wei(event['args']['fee'], 'ether'),
'orderId': event['args']['orderId']
})
# Create event filters
order_created_filter = gateway.events.OrderCreated.create_filter(fromBlock='latest')
order_settled_filter = gateway.events.OrderSettled.create_filter(fromBlock='latest')
order_refunded_filter = gateway.events.OrderRefunded.create_filter(fromBlock='latest')
# Poll for events
async def poll_events():
while True:
for event in order_created_filter.get_new_entries():
handle_order_created(event)
for event in order_settled_filter.get_new_entries():
handle_order_settled(event)
for event in order_refunded_filter.get_new_entries():
handle_order_refunded(event)
await asyncio.sleep(1)
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
func watchEvents(client *ethclient.Client) { // Create event filters orderCreatedSig := []byte("OrderCreated(address,address,uint256,bytes32,uint256)") orderSettledSig := []byte("OrderSettled(bytes32,address,uint256)") orderRefundedSig := []byte("OrderRefunded(bytes32,uint256)")
orderCreatedSigHash := crypto.Keccak256(orderCreatedSig)
orderSettledSigHash := crypto.Keccak256(orderSettledSig)
orderRefundedSigHash := crypto.Keccak256(orderRefundedSig)
query := ethereum.FilterQuery{
Addresses: []common.Address{gatewayAddress},
Topics: [][]common.Hash{
{common.BytesToHash(orderCreatedSigHash), common.BytesToHash(orderSettledSigHash), common.BytesToHash(orderRefundedSigHash)},
},
}
logs := make(chan types.Log)
sub, err := client.SubscribeFilterLogs(context.Background(), query, logs)
if err != nil {
log.Fatal(err)
}
for {
select {
case err := <-sub.Err():
log.Fatal(err)
case vLog := <-logs:
if vLog.Topics[0] == common.BytesToHash(orderCreatedSigHash) {
handleOrderCreated(vLog)
} else if vLog.Topics[0] == common.BytesToHash(orderSettledSigHash) {
handleOrderSettled(vLog)
} else if vLog.Topics[0] == common.BytesToHash(orderRefundedSigHash) {
handleOrderRefunded(vLog)
}
}
}
}
func handleOrderCreated(log types.Log) { fmt.Printf("Order Created: %+v\n", log) }
func handleOrderSettled(log types.Log) { fmt.Printf("Order Settled: %+v\n", log) }
func handleOrderRefunded(log types.Log) { fmt.Printf("Order Refunded: %+v\n", log) }
</Tab>
<Tab title="cURL">
```bash
# Event listening is typically done in your application code
# rather than with cURL. Use one of the programming language examples above.
async function retryTransaction(txFunction, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await txFunction(); } catch (error) { if (attempt === maxRetries) throw error; await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); } } }
</Tab>
<Tab title="Python">
```python
def handle_contract_error(error):
if "user rejected" in str(error).lower():
raise Exception("User rejected transaction")
elif "insufficient funds" in str(error).lower():
raise Exception("Insufficient USDT balance or ETH for gas")
elif "execution reverted" in str(error).lower():
raise Exception("Transaction reverted - check parameters")
else:
raise Exception(f"Contract error: {str(error)}")
async def retry_transaction(tx_function, max_retries=3):
for attempt in range(1, max_retries + 1):
try:
return await tx_function()
except Exception as error:
if attempt == max_retries:
raise error
await asyncio.sleep(1000 * attempt)
func handleContractError(err error) error { errStr := strings.ToLower(err.Error()) if strings.Contains(errStr, "user rejected") { return fmt.Errorf("user rejected transaction") } else if strings.Contains(errStr, "insufficient funds") { return fmt.Errorf("insufficient USDT balance or ETH for gas") } else if strings.Contains(errStr, "execution reverted") { return fmt.Errorf("transaction reverted - check parameters") } else { return fmt.Errorf("contract error: %v", err) } }
func retryTransaction(txFunction func() error, maxRetries int) error { for attempt := 1; attempt <= maxRetries; attempt++ { err := txFunction() if err == nil { return nil }
if attempt == maxRetries {
return err
}
time.Sleep(time.Duration(1000*attempt) * time.Millisecond)
}
return fmt.Errorf("max retries exceeded")
}
</Tab>
<Tab title="cURL">
```bash
# Error handling is typically done in your application code
# rather than with cURL. Use one of the programming language examples above.
class PaycrestGateway { constructor(publicClient, walletClient, gatewayAddress, usdtAddress) { this.provider = publicClient; this.walletClient = walletClient; this.gatewayAddress = gatewayAddress; this.usdtAddress = usdtAddress; this.gateway = null; this.usdt = null; }
async initialize() { this.gateway = getContract({ address: this.gatewayAddress, abi: GATEWAY_ABI, publicClient: this.provider, walletClient: this.walletClient }); this.usdt = getContract({ address: this.usdtAddress, abi: USDT_ABI, publicClient: this.provider, walletClient: this.walletClient }); this.setupEventListeners(); }
setupEventListeners() { this.provider.watchContractEvent({ address: this.gatewayAddress, abi: GATEWAY_ABI, eventName: 'OrderCreated', onLogs: this.handleOrderCreated.bind(this) }); this.provider.watchContractEvent({ address: this.gatewayAddress, abi: GATEWAY_ABI, eventName: 'OrderSettled', onLogs: this.handleOrderSettled.bind(this) }); this.provider.watchContractEvent({ address: this.gatewayAddress, abi: GATEWAY_ABI, eventName: 'OrderRefunded', onLogs: this.handleOrderRefunded.bind(this) }); }
async createOrder(amount, recipient, refundAddress) { try { const rate = await this.getExchangeRate(); const accountName = await this.verifyAccount(recipient); const messageHash = await this.encryptRecipientData({ ...recipient, accountName }); await this.approveUSDT(amount); const { request } = await this.gateway.simulate.createOrder({ args: [ this.usdtAddress, parseUnits(amount, 6), rate, zeroAddress, 0n, refundAddress, messageHash ] }); const hash = await this.walletClient.writeContract(request); const receipt = await this.provider.waitForTransactionReceipt({ hash }); return { orderId: this.extractOrderId(receipt), hash: receipt.hash }; } catch (error) { handleContractError(error); } } // ... other methods (getExchangeRate, verifyAccount, etc.) }
// Usage const paycrest = new PaycrestGateway( publicClient, walletClient, "0xE8bc3B607CfE68F47000E3d200310D49041148Fc", "0xdac17f958d2ee523a2206206994597c13d831ec7" );
await paycrest.initialize();
const order = await paycrest.createOrder( "100", // USDT amount { institution: "GTBINGLA", accountIdentifier: "123456789" }, "0x123..." // Refund address );
</Tab>
<Tab title="Python">
```python
from web3 import Web3
from eth_account import Account
import asyncio
class PaycrestGateway:
def __init__(self, w3, gateway_address, usdt_address):
self.w3 = w3
self.gateway_address = gateway_address
self.usdt_address = usdt_address
self.gateway = None
self.usdt = None
async def initialize(self):
self.gateway = self.w3.eth.contract(
address=self.gateway_address,
abi=GATEWAY_ABI
)
self.usdt = self.w3.eth.contract(
address=self.usdt_address,
abi=USDT_ABI
)
self.setup_event_listeners()
def setup_event_listeners(self):
# Event listeners would be set up here
pass
async def create_order(self, amount, recipient, refund_address):
try:
rate = await self.get_exchange_rate()
account_name = await self.verify_account(recipient)
message_hash = await self.encrypt_recipient_data({**recipient, 'accountName': account_name})
await self.approve_usdt(amount)
tx = self.gateway.functions.createOrder(
self.usdt_address,
self.w3.to_wei(amount, 'ether'),
rate,
'0x0000000000000000000000000000000000000000',
0,
refund_address,
message_hash
).build_transaction({
'from': user_address,
'gas': 200000,
'gasPrice': self.w3.eth.gas_price,
'nonce': self.w3.eth.get_transaction_count(user_address)
})
signed_tx = self.w3.eth.account.sign_transaction(tx, private_key)
tx_hash = self.w3.eth.send_raw_transaction(signed_tx.rawTransaction)
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
return {'orderId': self.extract_order_id(receipt), 'hash': receipt['transactionHash'].hex()}
except Exception as error:
handle_contract_error(error)
# ... other methods (get_exchange_rate, verify_account, etc.)
# Usage
w3 = Web3(Web3.HTTPProvider('https://mainnet.base.org'))
paycrest = PaycrestGateway(
w3,
"0xE8bc3B607CfE68F47000E3d200310D49041148Fc",
"0xdac17f958d2ee523a2206206994597c13d831ec7"
)
await paycrest.initialize()
order = await paycrest.create_order(
"100", # USDT amount
{
"institution": "GTBINGLA",
"accountIdentifier": "123456789"
},
"0x123..." # Refund address
)
import ( "context" "fmt" "log" "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
type PaycrestGateway struct { client *ethclient.Client gatewayAddress common.Address usdtAddress common.Address gateway *GatewayContract usdt *USDTContract }
func NewPaycrestGateway(client *ethclient.Client, gatewayAddr, usdtAddr string) *PaycrestGateway { return &PaycrestGateway{ client: client, gatewayAddress: common.HexToAddress(gatewayAddr), usdtAddress: common.HexToAddress(usdtAddr), } }
func (pg *PaycrestGateway) Initialize() error { // Initialize contracts with ABI bindings gateway, err := NewGatewayContract(pg.gatewayAddress, pg.client) if err != nil { return err } pg.gateway = gateway
usdt, err := NewUSDTContract(pg.usdtAddress, pg.client)
if err != nil {
return err
}
pg.usdt = usdt
pg.setupEventListeners()
return nil
}
func (pg *PaycrestGateway) setupEventListeners() { // Event listeners would be set up here }
func (pg *PaycrestGateway) CreateOrder(amount string, recipient map[string]interface{}, refundAddress string) error { rate, err := pg.getExchangeRate() if err != nil { return err }
accountName, err := pg.verifyAccount(recipient)
if err != nil {
return err
}
messageHash, err := pg.encryptRecipientData(recipient, accountName)
if err != nil {
return err
}
err = pg.approveUSDT(amount)
if err != nil {
return err
}
// Build transaction data
data := pg.buildCreateOrderData(amount, rate, refundAddress, messageHash)
// Create transaction
tx := &types.Transaction{
To: &pg.gatewayAddress,
Value: big.NewInt(0),
Gas: 200000,
GasPrice: big.NewInt(20000000000), // 20 gwei
Data: data,
}
// Sign and send transaction
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(8453)), privateKey)
if err != nil {
return err
}
err = pg.client.SendTransaction(context.Background(), signedTx)
if err != nil {
return err
}
fmt.Printf("Order created with hash: %s\n", signedTx.Hash().Hex())
return nil
}
// Usage func main() { client, err := ethclient.Dial("https://mainnet.base.org") if err != nil { log.Fatal(err) }
paycrest := NewPaycrestGateway(
client,
"0xE8bc3B607CfE68F47000E3d200310D49041148Fc",
"0xdac17f958d2ee523a2206206994597c13d831ec7",
)
err = paycrest.Initialize()
if err != nil {
log.Fatal(err)
}
recipient := map[string]interface{}{
"institution": "GTBINGLA",
"accountIdentifier": "123456789",
}
err = paycrest.CreateOrder("100", recipient, "0x123...")
if err != nil {
log.Fatal(err)
}
}
</Tab>
<Tab title="cURL">
```bash
# Smart contract interactions are typically done in your application code
# rather than with cURL. Use one of the programming language examples above.
- Base: Primary network for USDT/USDC transactions
- Polygon: Cost-effective transactions
- BNB Smart Chain: Binance ecosystem support
- Arbitrum One: High-performance L2 network
- Lisk: Alternative blockchain network
- Celo: Mobile-first blockchain (CUSD, CNGN)
Choose this method for full onchain control and direct smart contract interaction.