Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stellar): its example scripts #490

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion stellar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ node stellar/deploy-contract.js deploy axelar_gas_service --chain-name <CHAIN_NA
### Interchain Token Service

Deploy Interchain Token wasm first.

```bash
node stellar/deploy-contract.js deploy interchain_token --chain-name <CHAIN_NAME> --wasm-path ../axelar-cgp-soroban/target/wasm32-unknown-unknown/release/interchain_token.optimized.wasm
```bash

node stellar/deploy-contract.js deploy interchain_token_service --chain-name <CHAIN_NAME> --wasm-path ../axelar-cgp-soroban/target/wasm32-unknown-unknown/release/interchain_token_service.optimized.wasm
```

Expand Down Expand Up @@ -236,3 +237,29 @@ node stellar/gmp.js [source-chain] [message-id] [source-address] [payload]
# Example
node stellar/gmp.js execute avalanche '0x0bcbbfc9b006db6958f3fce75f11fdc306b45e8e43396211f414f40d2d6db7c5-0' 0xba76c6980428A0b10CFC5d8ccb61949677A61233 0x1234
```

### ITS Examples

#### Deploy Interchain Token

```bash
node stellar/its-example.js deploy-token [name] [symbol] [decimal] [salt] [initial-supply]
```

#### Deploy Remote Interchain Token

```bash
node stellar/its-example.js deploy-remote-token [salt] [destination-chain] [gas-token-address] [gas-fee-amount]
```

#### Send Interchain Token

```bash
node stellar/its-example.js send-token [token-id] [destination-chain] [destination-address] [amount] [data] [gas-token-address] [gas-fee-amount]
```

#### Execute

```bash
node stellar/its-example.js execute [source-chain] [message-id] [source-address] [payload]
ahramy marked this conversation as resolved.
Show resolved Hide resolved
```
17 changes: 1 addition & 16 deletions stellar/gmp.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,14 @@
const { Contract, Address, nativeToScVal } = require('@stellar/stellar-sdk');
const { Command } = require('commander');
const { loadConfig, printInfo, saveConfig } = require('../evm/utils');
const { getWallet, broadcast, addBaseOptions } = require('./utils');
const { getWallet, broadcast, addBaseOptions, tokenToScVal } = require('./utils');
const { addOptionsToCommands, getChainConfig } = require('../common');
const { ethers } = require('hardhat');
const {
utils: { arrayify },
} = ethers;
require('./cli-utils');

function tokenToScVal(tokenAddress, tokenAmount) {
return nativeToScVal(
{
address: Address.fromString(tokenAddress),
amount: tokenAmount,
},
{
type: {
address: ['symbol', 'address'],
amount: ['symbol', 'i128'],
},
},
);
}

async function send(wallet, _, chain, contractConfig, args, options) {
const contract = new Contract(contractConfig.address);
const caller = nativeToScVal(Address.fromString(wallet.publicKey()), { type: 'address' });
Expand Down
138 changes: 138 additions & 0 deletions stellar/its-example.js
ahramy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
'use strict';

const { Contract, Address, nativeToScVal } = require('@stellar/stellar-sdk');
const { Command } = require('commander');
const { loadConfig, saveConfig } = require('../evm/utils');
const { getWallet, broadcast, addBaseOptions, tokenToScVal, tokenMetadataToScVal } = require('./utils');
const { addOptionsToCommands, getChainConfig } = require('../common');
const { ethers } = require('hardhat');
const {
utils: { arrayify, hexZeroPad },
} = ethers;
require('./cli-utils');

async function deployToken(wallet, _, chain, contractConfig, args, options) {
ahramy marked this conversation as resolved.
Show resolved Hide resolved
const contract = new Contract(contractConfig.address);
ahramy marked this conversation as resolved.
Show resolved Hide resolved
const caller = nativeToScVal(Address.fromString(wallet.publicKey()), { type: 'address' });
const minter = nativeToScVal(Address.fromString(wallet.publicKey()), { type: 'address' });
ahramy marked this conversation as resolved.
Show resolved Hide resolved
const [symbol, name, decimal, salt, initialSupply] = args;
const saltBytes32 = hexZeroPad(salt.startsWith('0x') ? salt : '0x' + salt, 32);
ahramy marked this conversation as resolved.
Show resolved Hide resolved

const operation = contract.call(
'deploy_interchain_token',
caller,
nativeToScVal(Buffer.from(arrayify(saltBytes32)), { type: 'bytes' }),
tokenMetadataToScVal(decimal, name, symbol),
nativeToScVal(initialSupply, { type: 'i128' }),
minter,
);

await broadcast(operation, wallet, chain, 'Deploy Token', options);
ahramy marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should change the behaviour to not authorize all invocations by default, and authorize it explicitly.

}

async function deployRemoteToken(wallet, _, chain, contractConfig, args, options) {
ahramy marked this conversation as resolved.
Show resolved Hide resolved
const contract = new Contract(contractConfig.address);
const caller = nativeToScVal(Address.fromString(wallet.publicKey()), { type: 'address' });
const [salt, destinationChain, gasTokenAddress, gasFeeAmount] = args;
const saltBytes32 = hexZeroPad(salt.startsWith('0x') ? salt : '0x' + salt, 32);

const operation = contract.call(
'deploy_remote_interchain_token',
caller,
nativeToScVal(Buffer.from(arrayify(saltBytes32)), { type: 'bytes' }),
nativeToScVal(destinationChain, { type: 'string' }),
tokenToScVal(gasTokenAddress, gasFeeAmount),
);

await broadcast(operation, wallet, chain, 'Deploy Token', options);
}

async function sendToken(wallet, _, chain, contractConfig, args, options) {
const contract = new Contract(contractConfig.address);
const caller = nativeToScVal(Address.fromString(wallet.publicKey()), { type: 'address' });
const [tokenId, destinationChain, destinationAddress, amount, data, gasTokenAddress, gasFeeAmount] = args;

const operation = contract.call(
'interchain_transfer',
caller,
nativeToScVal(Buffer.from(arrayify(tokenId)), { type: 'bytes' }),
nativeToScVal(destinationChain, { type: 'string' }),
nativeToScVal(Buffer.from(arrayify(destinationAddress)), { type: 'bytes' }),
nativeToScVal(amount, { type: 'i128' }),
nativeToScVal(Buffer.from(arrayify(data)), { type: 'bytes' }),
tokenToScVal(gasTokenAddress, gasFeeAmount),
);

await broadcast(operation, wallet, chain, 'Send Token', options);
}

async function execute(wallet, _, chain, contractConfig, args, options) {
const contract = new Contract(contractConfig.address);
const [sourceChain, messageId, sourceAddress, payload] = args;

const operation = contract.call(
'execute',
nativeToScVal(sourceChain, { type: 'string' }),
nativeToScVal(messageId, { type: 'string' }),
nativeToScVal(sourceAddress, { type: 'string' }),
nativeToScVal(Buffer.from(arrayify(payload)), { type: 'bytes' }),
);

await broadcast(operation, wallet, chain, 'Execute Called', options);
ahramy marked this conversation as resolved.
Show resolved Hide resolved
}

async function mainProcessor(processor, args, options) {
const config = loadConfig(options.env);
const chain = getChainConfig(config, options.chainName);
const wallet = await getWallet(chain, options);

if (!chain.contracts?.interchain_token_service) {
throw new Error('Interchain Token Service package not found.');
}

await processor(wallet, config, chain, chain.contracts.interchain_token_service, args, options);

saveConfig(config, options.env);
}

if (require.main === module) {
const program = new Command();

program.name('its-example').description('Setllar ITS Example scripts.');

program
.name('deploy-token')
ahramy marked this conversation as resolved.
Show resolved Hide resolved
.description('deploy interchain token')
.command('deploy-token <symbol> <name> <decimals> <salt> <initialSupply> ')
.action((symbol, name, decimal, salt, initialSupply, options) => {
mainProcessor(deployToken, [symbol, name, decimal, salt, initialSupply], options);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also add canonical registration and deployment?

You should do an e2e test for that as well. To register and deploy XLM to Avalanche.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm facing an authorization issue with deployRemoteCanonicalToken. Work in progress.


program
.name('deploy-remote-token')
.description('deploy remote interchain token')
.command('deploy-remote-token <salt> <destinationChain> <gasTokenAddress> <gasFeeAmount>')
.action((salt, destinationChain, gasTokenAddress, gasFeeAmount, options) => {
mainProcessor(deployRemoteToken, [salt, destinationChain, gasTokenAddress, gasFeeAmount], options);
});

program
.name('send-token')
.description('send token')
.command('send-token <tokenId> <destinationChain> <destinationAddress> <amount> <data> <gasTokenAddress> <gasFeeAmount>')
ahramy marked this conversation as resolved.
Show resolved Hide resolved
.action((tokenId, destinationChain, destinationAddress, amount, data, gasTokenAddress, gasFeeAmount, options) => {
mainProcessor(sendToken, [tokenId, destinationChain, destinationAddress, amount, data, gasTokenAddress, gasFeeAmount], options);
});

program
.name('execute')
.description('execute a message')
.command('execute <sourceChain> <messageId> <sourceAddress> <payload>')
.action((sourceChain, messageId, sourceAddress, payload, options) => {
mainProcessor(execute, [sourceChain, messageId, sourceAddress, payload], options);
});

addOptionsToCommands(program, addBaseOptions);

program.parse();
}
35 changes: 35 additions & 0 deletions stellar/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
BASE_FEE,
xdr: { DiagnosticEvent, SorobanTransactionData },
Address,
nativeToScVal,
} = require('@stellar/stellar-sdk');
const { printInfo, sleep, addEnvOption } = require('../common');
const { Option } = require('commander');
Expand Down Expand Up @@ -278,6 +279,38 @@ function serializeValue(value) {
return value;
}

function tokenToScVal(tokenAddress, tokenAmount) {
return nativeToScVal(
{
address: Address.fromString(tokenAddress),
amount: tokenAmount,
},
{
type: {
address: ['symbol', 'address'],
amount: ['symbol', 'i128'],
},
},
);
}

function tokenMetadataToScVal(decimal, name, symbol) {
return nativeToScVal(
{
decimal,
name,
symbol,
},
{
type: {
decimal: ['symbol', 'u32'],
name: ['symbol', 'string'],
symbol: ['symbol', 'string'],
},
},
);
}

module.exports = {
stellarCmd,
ASSET_TYPE_NATIVE,
Expand All @@ -292,4 +325,6 @@ module.exports = {
getAmplifierVerifiers,
serializeValue,
getBalances,
tokenToScVal,
tokenMetadataToScVal,
};
Loading