Skip to main content

Client Examples

Collection of client samples for various EVM Security Token v5 features.

See Relayer API utils for the utilities used in the examples.

Grant Role

import { Wallet } from 'ethers'
import { createMetaTx } from './test/utils/cmkv5/transactions/createMetaTx'
import { createTxDataForGrantRole } from './test/utils/cmkv5/transactions/createTxData'
import { sign } from 'tweetnacl'
import { createReqSignature } from './test/utils/api/createReqSignature'

async function main() {
const functionArgs = [
'0x5B7ebc132cC190058A1C153FcE07475db721bd1b', // Wallet address
'16', // Role
]
const contractAddress = '0x4eCe884Cfee1F9FFCE9F46a601E6ED3E0CcBFCeD' // AccessControl contract address
const forwarderAddr = '0x826688fadd6297671f7cB7dd780e825689bed5AA' // Forwarder contract address
const forwarderChainId = 43113 // Avalanche Fuji chain ID
const signerSk = String(
require('fs')
.readFileSync('.example-signer-sk-contract-admin-local', 'utf8')
.trim()
)
const signer = new Wallet(signerSk)

const metaTxWithSig = await createMetaTx(
{
from: signer.address,
to: contractAddress,
value: 0,
gas: 50000000,
nonce: new Date().getTime(),
deadline: Math.floor(new Date().getTime() / 1000) + 1 * 60 * 60,
data: createTxDataForGrantRole({
to: String(functionArgs[0]),
role: parseInt(String(functionArgs[1])),
}),
signature: '',
},
forwarderAddr,
forwarderChainId,
signer
)

console.log(metaTxWithSig)

const callbackUrl =
'https://webhook.site/cdd23e90-9315-4268-a29f-655bb38b38a5'
const timestamp = new Date().getTime()
const requestBody = {
metaTx: metaTxWithSig,
forwarderAddress: forwarderAddr,
callback: {
url: callbackUrl,
},
timestamp,
}

const keyPair = sign.keyPair.fromSecretKey(
Buffer.from(
String(
require('fs').readFileSync('.example-api-key-local', 'utf8').trim()
),
'base64'
)
)
const signature = createReqSignature(requestBody, keyPair.secretKey)
const sigB64 = Buffer.from(signature).toString('base64')
const pkB64 = Buffer.from(keyPair.publicKey).toString('base64')

console.log(requestBody)
console.log(sigB64)

const resp = await fetch(
'https://bi6fxskpk4.execute-api.localhost.localstack.cloud:4566/prod/api/v1/relay_meta_tx',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Request-Pk-B64': pkB64,
'X-Request-Sig-B64': sigB64,
},
body: JSON.stringify(requestBody),
}
)

if (resp.status !== 201) {
throw new Error(`Failed to submit meta tx: ${await resp.text()}`)
}
}

main()

Set Identity

import { Wallet } from 'ethers'
import { createMetaTx } from './test/utils/cmkv5/transactions/createMetaTx'
import { createTxDataForSetIdentity } from './test/utils/cmkv5/transactions/createTxData'
import { sign } from 'tweetnacl'
import { createReqSignature } from './test/utils/api/createReqSignature'

async function main() {
const functionArgs = [
'0x5B7ebc132cC190058A1C153FcE07475db721bd1b', // Wallet address
'1', // Regions
'1', // Accreditation
'1757602105', // AML/KYC Timestamp
'1757602105', // Accreditation Timestamp
'true', // AML/KYC Passed
]
const contractAddress = '0xBc4c6a27141CAB3CC7291725B30079d1CD117116' // IdentityRegistry contract address
const forwarderAddr = '0x826688fadd6297671f7cB7dd780e825689bed5AA' // Forwarder contract address
const forwarderChainId = 43113
const signerSk = String(
require('fs')
.readFileSync('.example-signer-sk-wallets-admin-local', 'utf8')
.trim()
)
const signer = new Wallet(signerSk)

const metaTxWithSig = await createMetaTx(
{
from: signer.address,
to: contractAddress,
value: 0,
gas: 50000000,
nonce: new Date().getTime(),
deadline: Math.floor(new Date().getTime() / 1000) + 1 * 60 * 60,
data: createTxDataForSetIdentity({
destination: String(functionArgs[0]),
identityInfo: {
regions: [parseInt(String(functionArgs[1]))],
accreditationType: parseInt(String(functionArgs[2])),
lastAmlKycChangeTimestamp: parseInt(String(functionArgs[3])),
lastAccreditationChangeTimestamp: parseInt(String(functionArgs[4])),
amlKycPassed: functionArgs[5] === 'true',
},
}),
signature: '',
},
forwarderAddr,
forwarderChainId,
signer
)

console.log(metaTxWithSig)

const callbackUrl =
'https://webhook.site/cdd23e90-9315-4268-a29f-655bb38b38a5'
const timestamp = new Date().getTime()
const requestBody = {
metaTx: metaTxWithSig,
forwarderAddress: forwarderAddr,
callback: {
url: callbackUrl,
},
timestamp,
}

const keyPair = sign.keyPair.fromSecretKey(
Buffer.from(
String(
require('fs').readFileSync('.example-api-key-local', 'utf8').trim()
),
'base64'
)
)
const signature = createReqSignature(requestBody, keyPair.secretKey)
const sigB64 = Buffer.from(signature).toString('base64')
const pkB64 = Buffer.from(keyPair.publicKey).toString('base64')

console.log(requestBody)
console.log(sigB64)

const resp = await fetch(
'https://bi6fxskpk4.execute-api.localhost.localstack.cloud:4566/prod/api/v1/relay_meta_tx',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Request-Pk-B64': pkB64,
'X-Request-Sig-B64': sigB64,
},
body: JSON.stringify(requestBody),
}
)

if (resp.status !== 201) {
throw new Error(`Failed to submit meta tx: ${await resp.text()}`)
}
}

main()

Set Token Type Rule

import { Wallet } from 'ethers'
import { createMetaTx } from './test/utils/cmkv5/transactions/createMetaTx'
import { createTxDataForSetTokenTypeRule } from './test/utils/cmkv5/transactions/createTxData'
import { sign } from 'tweetnacl'
import { createReqSignature } from './test/utils/api/createReqSignature'

async function main() {
const functionArgs = [
'1', // Region
'1', // Accreditation
//
'1', // Token Type
'true', // Requires AML/KYC
'true', // Is Active
]
const contractAddress = '0x2494C44FCA98A67e0248D0687D1F078D7e508bbc' // TransferRules contract address
const forwarderAddr = '0x826688fadd6297671f7cB7dd780e825689bed5AA' // Forwarder contract address
const forwarderChainId = 43113
const signerSk = String(
require('fs')
.readFileSync('.example-signer-sk-transfer-admin-local', 'utf8')
.trim()
)
const signer = new Wallet(signerSk)

const metaTxWithSig = await createMetaTx(
{
from: signer.address,
to: contractAddress,
value: 0,
gas: 50000000,
nonce: new Date().getTime(),
deadline: Math.floor(new Date().getTime() / 1000) + 1 * 60 * 60,
data: createTxDataForSetTokenTypeRule({
region: parseInt(String(functionArgs[0])),
accreditation: parseInt(String(functionArgs[1])),
tokenType: parseInt(String(functionArgs[2])),
requiresAmlKyc: functionArgs[3] === 'true',
isActive: functionArgs[4] === 'true',
}),
signature: '',
},
forwarderAddr,
forwarderChainId,
signer
)

console.log(metaTxWithSig)

const callbackUrl =
'https://webhook.site/cdd23e90-9315-4268-a29f-655bb38b38a5'
const timestamp = new Date().getTime()
const requestBody = {
metaTx: metaTxWithSig,
forwarderAddress: forwarderAddr,
callback: {
url: callbackUrl,
},
timestamp,
}

const keyPair = sign.keyPair.fromSecretKey(
Buffer.from(
String(
require('fs').readFileSync('.example-api-key-local', 'utf8').trim()
),
'base64'
)
)
const signature = createReqSignature(requestBody, keyPair.secretKey)
const sigB64 = Buffer.from(signature).toString('base64')
const pkB64 = Buffer.from(keyPair.publicKey).toString('base64')

console.log(requestBody)
console.log(sigB64)

const resp = await fetch(
'https://bi6fxskpk4.execute-api.localhost.localstack.cloud:4566/prod/api/v1/relay_meta_tx',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Request-Pk-B64': pkB64,
'X-Request-Sig-B64': sigB64,
},
body: JSON.stringify(requestBody),
}
)

if (resp.status !== 201) {
throw new Error(`Failed to submit meta tx: ${await resp.text()}`)
}
}

main()

Mint

import { Wallet } from 'ethers'
import { createMetaTx } from './test/utils/cmkv5/transactions/createMetaTx'
import { createTxDataForMint } from './test/utils/cmkv5/transactions/createTxData'
import { sign } from 'tweetnacl'
import { createReqSignature } from './test/utils/api/createReqSignature'

async function main() {
const functionArgs = [
'0x5B7ebc132cC190058A1C153FcE07475db721bd1b', // Recipient
'100', // Amount
]
const contractAddress = '0x1a35dc5e96A60941cB8cCbD869a897B1f68A7955' // Token contract address
const forwarderAddr = '0x826688fadd6297671f7cB7dd780e825689bed5AA' // Forwarder contract address
const forwarderChainId = 43113
const signerSk = String(
require('fs')
.readFileSync('.example-signer-sk-reserve-admin-local', 'utf8')
.trim()
)
const signer = new Wallet(signerSk)

const metaTxWithSig = await createMetaTx(
{
from: signer.address,
to: contractAddress,
value: 0,
gas: 50000000,
nonce: new Date().getTime(),
deadline: Math.floor(new Date().getTime() / 1000) + 1 * 60 * 60,
data: createTxDataForMint({
to: String(functionArgs[0]),
value: parseInt(String(functionArgs[1])),
}),
signature: '',
},
forwarderAddr,
forwarderChainId,
signer
)

console.log(metaTxWithSig)

const callbackUrl =
'https://webhook.site/cdd23e90-9315-4268-a29f-655bb38b38a5'
const timestamp = new Date().getTime()
const requestBody = {
metaTx: metaTxWithSig,
forwarderAddress: forwarderAddr,
callback: {
url: callbackUrl,
},
timestamp,
}

const keyPair = sign.keyPair.fromSecretKey(
Buffer.from(
String(
require('fs').readFileSync('.example-api-key-local', 'utf8').trim()
),
'base64'
)
)
const signature = createReqSignature(requestBody, keyPair.secretKey)
const sigB64 = Buffer.from(signature).toString('base64')
const pkB64 = Buffer.from(keyPair.publicKey).toString('base64')

console.log(requestBody)
console.log(sigB64)

const resp = await fetch(
'https://bi6fxskpk4.execute-api.localhost.localstack.cloud:4566/prod/api/v1/relay_meta_tx',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Request-Pk-B64': pkB64,
'X-Request-Sig-B64': sigB64,
},
body: JSON.stringify(requestBody),
}
)

if (resp.status !== 201) {
throw new Error(`Failed to submit meta tx: ${await resp.text()}`)
}
}

main()