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()