Skip to content

Commit

Permalink
feat(Stellar): operators execute script (#229)
Browse files Browse the repository at this point in the history
* add stellar sdk

* add stellar to chain configs

* add stellar utils and operators scripts

* feat(Stellar): Operators execute script

* feat(Stellar): Operators refund gas

* cleanup

* ftm gas price revert

* add retry

* prettier

* lint

* Update stellar/operators.js

Co-authored-by: Milap Sheth <milap@interoplabs.io>

* Update stellar/operators.js

Co-authored-by: Milap Sheth <milap@interoplabs.io>

* fix(Stellar): Operators PR feedback

---------

Co-authored-by: Milap Sheth <milap@interoplabs.io>
  • Loading branch information
re1ro and milapsheth authored Jun 13, 2024
1 parent 8c61965 commit 019d41f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 39 deletions.
36 changes: 6 additions & 30 deletions evm/operators.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ const {
printInfo,
printError,
printWalletInfo,
isNumber,
isAddressArray,
isNumberArray,
isKeccak256Hash,
parseArgs,
prompt,
getGasOptions,
Expand Down Expand Up @@ -192,43 +190,21 @@ async function processCommand(config, chain, options) {
}

case 'refund': {
const txHash = argsArray[0];
const logIndex = argsArray[1];
const receiver = argsArray[2];
const token = argsArray[3];
const amount = argsArray[4];
const [txHash, logIndex, receiver, token, amount] = argsArray;

const isOperator = await operatorsContract.isOperator(wallet.address);

if (!isOperator) {
throw new Error(`Caller ${wallet.address} is not an operator.`);
}

if (!isKeccak256Hash(txHash)) {
throw new Error(`Invalid tx hash: ${txHash}`);
}

if (!isNumber(logIndex)) {
throw new Error(`Invalid log index: ${logIndex}`);
}

if (!isAddress(receiver)) {
throw new Error(`Invalid receiver address: ${receiver}`);
}

if (!isAddress(token)) {
throw new Error(`Invalid token address: ${token}`);
}

if (!isNumber(amount)) {
throw new Error(`Invalid token amount: ${amount}`);
}

const target = chain.contracts.AxelarGasService?.address;

if (!isAddress(target)) {
throw new Error(`Missing AxelarGasService address in the chain info.`);
}
validateParameters({
isKeccak256Hash: { txHash },
isNumber: { logIndex, amount },
isAddress: { receiver, token, target },
});

const gasServiceInterface = new Interface(getContractJSON('IAxelarGasService').abi);
const refundCalldata = gasServiceInterface.encodeFunctionData('refund', [txHash, logIndex, receiver, token, amount]);
Expand Down
81 changes: 72 additions & 9 deletions stellar/operators.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { Contract, Address } = require('@stellar/stellar-sdk');
const { Contract, Address, nativeToScVal } = require('@stellar/stellar-sdk');
const { Command, Option } = require('commander');
const { getWallet, prepareTransaction, buildTransaction, sendTransaction, estimateCost } = require('./utils');
const { loadConfig, printInfo } = require('../evm/utils');
const { loadConfig, printInfo, parseArgs, validateParameters } = require('../evm/utils');
require('./cli-utils');

async function processCommand(options, _, chain) {
Expand All @@ -11,21 +11,82 @@ async function processCommand(options, _, chain) {

let operation;

const address = Address.fromString(options.args || wallet.publicKey());

switch (options.action) {
case 'is_operator': {
operation = contract.call('is_operator', address.toScVal());
if (!options.args) {
throw new Error(`Missing --args operatorAddress the params.`);
}

const operator = Address.fromString(options.args).toScVal();
operation = contract.call('is_operator', operator);
break;
}

case 'add_operator': {
operation = contract.call('add_operator', address.toScVal());
if (!options.args) {
throw new Error(`Missing --args operatorAddress the params.`);
}

const operator = Address.fromString(options.args).toScVal();
operation = contract.call('add_operator', operator);
break;
}

case 'remove_operator': {
operation = contract.call('remove_operator', address.toScVal());
if (!options.args) {
throw new Error(`Missing --args operatorAddress the params.`);
}

const operator = Address.fromString(options.args).toScVal();
operation = contract.call('remove_operator', operator);
break;
}

case 'refund': {
const operator = Address.fromString(wallet.publicKey()).toScVal();
const gasService = options.target || chain.contracts?.axelar_gas_service?.address;

if (!gasService) {
throw new Error(`Missing AxelarGasService address in the chain info.`);
}

const target = Address.fromString(gasService).toScVal();
const method = nativeToScVal('refund', { type: 'symbol' });
const [messageId, receiver, tokenAddress, tokenAmount] = parseArgs(options.args || '');

validateParameters({
isNonEmptyString: { messageId, receiver, tokenAddress },
isValidNumber: { tokenAmount },
});

const args = nativeToScVal([
messageId,
Address.fromString(receiver),
{ address: Address.fromString(tokenAddress), amount: tokenAmount },
]);

operation = contract.call('execute', operator, target, method, args);
break;
}

case 'execute': {
const operator = Address.fromString(wallet.publicKey()).toScVal();

if (!options.target) {
throw new Error(`Missing target address param.`);
}

const target = Address.fromString(options.target).toScVal();

if (!options.method) {
throw new Error(`Missing method name param.`);
}

const method = nativeToScVal(options.method, { type: 'symbol' });

const args = nativeToScVal(parseArgs(options.args || ''));

operation = contract.call('execute', operator, target, method, args);
break;
}

Expand Down Expand Up @@ -66,12 +127,14 @@ if (require.main === module) {
program.addOption(new Option('-v, --verbose', 'verbose output').default(false));
program.addOption(
new Option('--action <action>', 'operator contract action')
.choices(['is_operator', 'add_operator', 'remove_operator'])
.choices(['is_operator', 'add_operator', 'remove_operator', 'refund', 'execute'])
.makeOptionMandatory(true),
);
program.addOption(new Option('--estimateCost', 'estimate on-chain resources').default(false));
program.addOption(new Option('--address <address>', 'operators contract address'));
program.addOption(new Option('--args <args>', 'arguments for the contract call'));
program.addOption(new Option('--address <address>', 'contract address'));
program.addOption(new Option('--target <target>', 'target contract for the execute call'));
program.addOption(new Option('--method <method>', 'target method for the execute call'));

program.action((options) => {
const config = loadConfig(options.env);
Expand Down

0 comments on commit 019d41f

Please sign in to comment.