Skip to content

Commit

Permalink
Deploy a Stellar Asset Contract (SAC) for a Stellar asset using code (#…
Browse files Browse the repository at this point in the history
…887)

* chores: initialization of SAC using code

* chores: added code walk through

* chores: code explanation
git add .

* chores: final code explaination

* editorial

* chores: updated code nitpicks

* chores: editorial fix

* Update docs/build/guides/conventions/deploy-sac-with-code.mdx

* Update docs/build/guides/conventions/deploy-sac-with-code.mdx

---------

Co-authored-by: Bri <[email protected]>
Co-authored-by: Chris Anatalio <[email protected]>
  • Loading branch information
3 people authored and janewang committed Sep 12, 2024
1 parent 3d6b23c commit 2907c52
Showing 1 changed file with 242 additions and 0 deletions.
242 changes: 242 additions & 0 deletions docs/build/guides/conventions/deploy-sac-with-code.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
---
title: Deploy a SAC for a Stellar asset using code
description: Deploy a SAC for a Stellar asset using Javascript SDK
---

<head>
<title>
{`Deploy a Stellar Asset Contract (SAC) for a Stellar asset using code`}
</title>
<meta charSet="utf-8" />
<meta
property="og:title"
content="Deploy a Stellar Asset Contract (SAC) for a Stellar asset using code"
/>
<meta
property="og:description"
content="This is a step-by-step guide to help you deploy a SAC for a Stellar asset using the Stellar SDK."
/>
</head>

## Overview

In this guide, you'll learn how to deploy a [Stellar Asset Contract (SAC)](../../../tokens/stellar-asset-contract.mdx) for a Stellar asset using the [Stellar SDK](../../../tools/sdks/library.mdx#javascript-sdk). The Stellar SDK is a set of tools and library designed to help developers build applications that interact with the Stellar blockchain network.

### Prerequisites:

- [Node.js ](https://nodejs.org/en) and npm installed.
- Stellar SDK for [JavaScript](https://www.npmjs.com/package/@stellar/stellar-sdk) installed
- [Knowledge about Issuing an Asset on Stellar](https://developers.stellar.org/docs/tokens/how-to-issue-an-asset)

## Code overview

```javascript title="deployassetcontract.js"
import * as StellarSdk from "@stellar/stellar-sdk";

const networkRPC = "https://soroban-testnet.stellar.org";
const server = new StellarSdk.SorobanRpc.Server(networkRPC);
const network_passphrase = StellarSdk.Networks.TESTNET;

async function yeetTx(feedback, message) {
try {
if (feedback.status !== "PENDING") {
throw feedback;
}

let status;
let attempts = 0;
while (attempts++ < 20) {
// A maximum of 20 polls of transaction status
const tmpStatus = await server.getTransaction(feedback.hash);
switch (tmpStatus.status) {
case "FAILED":
throw tmpStatus;
case "NOT_FOUND":
await sleep(1000); // Wait for one minute
continue;
case "SUCCESS":
status = tmpStatus;
console.log(`${message}: Transaction succeeded`, status);
break;
}
if (status) break;
}

if (attempts >= 20 || !status) {
throw new Error(
`Failed to find transaction ${feedback.hash} after ${attempts} attempts.`,
);
}

return status;
} catch (error) {
console.error("Transaction failed:", error);
throw error;
}
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

const deployStellarAssetContract = async () => {
const sourceSecrets =
"SASI6PA4K52GQJF6BC263GLYOADVKFJ4SZ7TFX4QQF2U76T3EJ54DT7Y"; // Replace with your Secret Key
const sourceKeypair = StellarSdk.Keypair.fromSecret(sourceSecrets);
const sourceAccount = await server.getAccount(sourceKeypair.publicKey());

try {
const assetCode = "JOEBOY";
const issuerPublicKey = sourceKeypair.publicKey();
const customAsset = new StellarSdk.Asset(assetCode, issuerPublicKey);

const transaction = new StellarSdk.TransactionBuilder(sourceAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: network_passphrase,
})
.addOperation(
StellarSdk.Operation.createStellarAssetContract({
asset: customAsset,
}),
)
.setTimeout(30)
.build();

const uploadTx = await server.prepareTransaction(transaction);
uploadTx.sign(sourceKeypair);

const result = await server.sendTransaction(uploadTx);
const feedback = await yeetTx(result, `SACTransactionFeeback`);
const contractBuffer = feedback.returnValue._value._value;
const contractID = StellarSdk.StrKey.encodeContract(contractBuffer);
console.log(`ContractID of Our ${customAsset.code} Asset`, contractID);
} catch (e) {
console.error("An error occurred while Deploying assets:", e);
}
};

await deployStellarAssetContract();
```

## Code explanation

**Server Setup**

```javascript
import * as StellarSdk from "@stellar/stellar-sdk";

const networkRPC = "https://soroban-testnet.stellar.org";
const server = new StellarSdk.SorobanRpc.Server(networkRPC);
const network_passphrase = StellarSdk.Networks.TESTNET;
```

- `networkRPC`: The URL for the Soroban testnet.
- `server`: A new instance of `SorobanRpc.Server` is created, which will be used to interact with the Soroban testnet.
- `network_passphrase`: sets the network passphrase to the TESTNET

**`yeetTx` function**

```javascript
async function yeetTx(feedback, message) {
try {
if (feedback.status !== "PENDING") {
throw feedback;
}

let status;
let attempts = 0;
while (attempts++ < 20) {
const tmpStatus = await server.getTransaction(feedback.hash);
switch (tmpStatus.status) {
case "FAILED":
throw tmpStatus;
case "NOT_FOUND":
await sleep(1000);
continue;
case "SUCCESS":
status = tmpStatus;
console.log(`${message}: Transaction succeeded`, status);
break;
}
if (status) break;
}

if (attempts >= 20 || !status) {
throw new Error(
`Failed to find transaction ${feedback.hash} after ${attempts} attempts.`,
);
}

return status;
} catch (error) {
console.error("Transaction failed:", error);
throw error;
}
}
```

The `yeetTx` function handles checking the status of a transaction until it either succeeds, fails, or the number of attempts exceeds a limit.

- `feedback`: The initial feedback object returned when a transaction is submitted.
- `message`: A custom message to log when the transaction succeeds..

**`sleep` function**

```javascript
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
```

This function is a helper that returns a promise that resolves after a specified number of milliseconds. It's used to delay the next check in yeetTx when the transaction status is "NOT_FOUND."

**`DeployStellarAssetContract` function**

```javascript
const deployStellarAssetContract = async () => {
const sourceSecrets =
"SASI6PA4K52GQJF6BC263GLYOADVKFJ4SZ7TFX4QQF2U76T3EJ54DT7Y"; // Replace with your Secret Key
const network_passphrase = StellarSdk.Networks.TESTNET;
const sourceKeypair = StellarSdk.Keypair.fromSecret(sourceSecrets);
const sourceAccount = await server.getAccount(sourceKeypair.publicKey());

try {
const assetCode = "JOEBOY";
const issuerPublicKey = sourceKeypair.publicKey();
const customAsset = new StellarSdk.Asset(assetCode, issuerPublicKey);

const transaction = new StellarSdk.TransactionBuilder(sourceAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: network_passphrase,
})
.addOperation(
StellarSdk.Operation.createStellarAssetContract({
asset: customAsset,
}),
)
.setTimeout(30)
.build();

const uploadTx = await server.prepareTransaction(transaction);
uploadTx.sign(sourceKeypair);

const result = await server.sendTransaction(uploadTx);
const feedback = await yeetTx(result, `SACTransactionFeeback`);
const contractBuffer = feedback.returnValue._value._value;
const contractID = StellarSdk.StrKey.encodeContract(contractBuffer);
console.log(`ContractID of Our ${customAsset.code} Asset`, contractID);
} catch (e) {
console.error("An error occurred while Deploying assets:", e);
}
};

await deployStellarAssetContract();
```

This function is designed to deploy a Stellar Asset Contract (SAC) on the Soroban testnet.

- **Secret Key**: It starts by defining the secret key for the source account (`sourceSecrets`), which you must replace with your own.
- **Keypair and Account**: Generates the keypair from the secret key and fetches the account details from the Soroban server.
- **Custom Asset**: Defines a custom asset with the code `JOEBOY` and the issuer's public key.
- **Transaction Building**: A transaction is built using the `TransactionBuilder`, which includes the `createStellarAssetContract` operation for the custom asset. The transaction is then prepared and signed.
- **Send Transaction**: The signed transaction is sent to the network using `server.sendTransaction`.
- **Feedback Handling**: It waits for the transaction feedback using the `yeetTx` function to ensure it has succeeded. extracts the contract buffer from the feedback and converts it to a contract ID using `StellarSdk.StrKey.encodeContract`. finally, it logs the contract ID for the deployed asset.

0 comments on commit 2907c52

Please sign in to comment.