Skip to content

Commit

Permalink
add smart contract interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
juliancwirko committed Jun 29, 2024
1 parent 4648074 commit 498692a
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 15 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ git checkout <tag_name>
- **Article**: [Mastering smart contract deployment with MultiversX JavaScript SDK](https://www.julian.io/articles/multiversx-js-sdk-sc-deployment.html)
- **Video**: [Mastering smart contract deployment with MultiversX JavaScript SDK](https://www.youtube.com/watch?v=Rk-vHqd2avs)

### Example 4: Smart contract interactions

- **Tag**: `smart-contract-interactions`
- **Description**: This example demonstrates how to interact with a smart contract using the MultiversX JavaScript SDK on the devnet.
- **Article**: [Step-by-step guide to MultiversX smart contract interactions with JavaScript SDK](https://www.julian.io/articles/multiversx-js-sdk-sc-interactions.html)
- **Video**: [Step-by-step guide to MultiversX smart contract interactions with JavaScript SDK](https://www.youtube.com/watch?v=TMDC5yxT4_c)

## Security and Wallet Information

The examples use a demo wallet with a hardcoded password. All interactions occur on the **devnet** (development network of MultiversX), ensuring that it is safe to expose the wallet credentials. The devnet is designed for testing and development, involving no real assets. Don't do this on the mainnet.
Expand Down
6 changes: 3 additions & 3 deletions deploy-smart-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
SmartContractTransactionsFactory,
Code,
Address,
AbiRegistry,
TransactionWatcher,
SmartContractTransactionsOutcomeParser,
TransactionsConverter,
Expand All @@ -29,12 +30,13 @@ const deploySmartContract = async () => {
// Load ABI file (not required for now, but will be useful when interacting with the SC)
// Although it would be helpful if we had initial arguments to pass
const abiFile = await promises.readFile("./piggybank.abi.json", "UTF-8");
const abiObj = JSON.parse(abiFile);

// Prepare transfer transactions factory
const factoryConfig = new TransactionsFactoryConfig({ chainID: "D" });
let scFactory = new SmartContractTransactionsFactory({
config: factoryConfig,
abi: abiFile,
abi: AbiRegistry.create(abiObj),
});

// Prepare deploy transaction
Expand Down Expand Up @@ -82,8 +84,6 @@ const deploySmartContract = async () => {
converter.transactionOnNetworkToOutcome(transactionOnNetwork);
const parsedOutcome = parser.parseDeploy({ transactionOutcome });

console.log(parsedOutcome);

console.log(
`Smart Contract deployed. Here it is:\nhttps://devnet-explorer.multiversx.com/accounts/${parsedOutcome.contracts[0].address}\n\nCheck the transaction in the Explorer:\nhttps://devnet-explorer.multiversx.com/transactions/${txHash}`
);
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"license": "MIT",
"dependencies": {
"@multiversx/sdk-core": "^13.1.0",
"@multiversx/sdk-core": "^13.2.1",
"@multiversx/sdk-network-providers": "^2.4.3",
"@multiversx/sdk-wallet": "^4.4.0"
"@multiversx/sdk-wallet": "^4.5.0"
}
}
}
146 changes: 146 additions & 0 deletions smart-contract-interactions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { promises } from "node:fs";
import {
Address,
SmartContractTransactionsFactory,
TransactionsFactoryConfig,
TransactionComputer,
AbiRegistry,
QueryRunnerAdapter,
SmartContractQueriesController,
} from "@multiversx/sdk-core";
import {
syncAndGetAccount,
senderAddress,
getSigner,
apiNetworkProvider,
} from "./setup.js";

/**
* Replace with your own deployed piggy bank smart contract
* check deploy-smart-contract.js on how to deploy one
*/
const PIGGYBANK_CONTRACT_ADDRESS =
"erd1qqqqqqqqqqqqqpgqtrajzw4vq0zxccdt9u66cvgg6vz8c6cwnegqkfqkpq";

/**
* Load ABI file
*/
const getAbi = async () => {
const abiFile = await promises.readFile("./piggybank.abi.json", "UTF-8");
return JSON.parse(abiFile);
};

const scTransaction = async ({ functionName, args, amount }) => {
const user = await syncAndGetAccount();
const computer = new TransactionComputer();
const signer = await getSigner();

const abiObj = await getAbi();

const factoryConfig = new TransactionsFactoryConfig({ chainID: "D" });
const factory = new SmartContractTransactionsFactory({
config: factoryConfig,
abi: AbiRegistry.create(abiObj),
});

const transaction = factory.createTransactionForExecute({
sender: new Address(senderAddress),
contract: Address.fromBech32(PIGGYBANK_CONTRACT_ADDRESS),
function: functionName,
gasLimit: 5000000,
arguments: args || [],
nativeTransferAmount: amount,
});

// Increase the nonce
transaction.nonce = user.getNonceThenIncrement();

// Serialize the transaction for signing
const serializedTransaction = computer.computeBytesForSigning(transaction);

// Sign the transaction with our signer
transaction.signature = await signer.sign(serializedTransaction);

// Broadcast the transaction
const txHash = await apiNetworkProvider.sendTransaction(transaction);

console.log(
"Check in the Explorer: ",
`https://devnet-explorer.multiversx.com/transactions/${txHash}`
);
};

/**
* Call the createPiggy endpoint on the PiggyBank smart contract
* https://github.com/xdevguild/piggy-bank-sc/blob/master/src/lib.rs#L25
* We pass the unix timestamp in the future
*/
const createPiggy = async () => {
await scTransaction({
functionName: "createPiggy",
args: [1750686756],
});
};

/**
* Call the addAmount endpoint on the PiggyBank smart contract
* https://github.com/xdevguild/piggy-bank-sc/blob/master/src/lib.rs#L42
*/
const addAmount = async () => {
await scTransaction({
functionName: "addAmount",
amount: 1000000000000000n,
});
};

/**
* Query the getLockedAmount endpoint on the PiggyBank smart contract
* https://github.com/xdevguild/piggy-bank-sc/blob/master/src/lib.rs#L92
*/
const getLockedAmount = async () => {
const abiObj = await getAbi();

const queryRunner = new QueryRunnerAdapter({
networkProvider: apiNetworkProvider,
});

const controller = new SmartContractQueriesController({
queryRunner: queryRunner,
abi: AbiRegistry.create(abiObj),
});

const query = controller.createQuery({
contract: PIGGYBANK_CONTRACT_ADDRESS,
function: "getLockedAmount",
arguments: [senderAddress],
});

const response = await controller.runQuery(query);

const [amount] = controller.parseQueryResponse(response);

// The returned amount is a BigNumber
console.log("Locked amount is: ", amount.valueOf());
};

/**
* Here we will manage which function to call
*/
const smartContractInteractions = () => {
const args = process.argv.slice(2);
const functionName = args[0];

const functions = {
createPiggy,
addAmount,
getLockedAmount,
};

if (functionName in functions) {
functions[functionName]();
} else {
console.log("Function not found!");
}
};

smartContractInteractions();

0 comments on commit 498692a

Please sign in to comment.