Skip to content

Commit

Permalink
Merge pull request #952 from hirosystems/develop
Browse files Browse the repository at this point in the history
update stacks.js content and code examples
  • Loading branch information
ryanwaits authored Feb 7, 2025
2 parents 12f4389 + 499ac40 commit 897c261
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Testnet: `ST2F4BK4GZH6YFBNHYDDGN4T1RKBA7DA1BJZPJEJJ`

### Using Stacks Connect

```ts
```tsx -n
import { showConnect } from '@stacks/connect';

showConnect({
Expand All @@ -31,8 +31,9 @@ showConnect({

### Using a seed phrase / mnemonic / private key

```ts
import { randomSeedPhrase, generateWallet, privateKeyToAddress } from "@stacks/wallet-sdk";
```ts -n
import { randomSeedPhrase, generateWallet } from "@stacks/wallet-sdk";
import { privateKeyToAddress } from "@stacks/transactions";

const seed = randomSeedPhrase();

Expand All @@ -47,7 +48,7 @@ const address = privateKeyToAddress(wallet.accounts[0].stxPrivateKey, 'mainnet')

### Using a public key

```ts
```ts -n
import { publicKeyToAddress } from '@stacks/transactions';

const address = publicKeyToAddress(publicKey, 'mainnet');
Expand Down
22 changes: 11 additions & 11 deletions content/docs/stacks/stacks.js/concepts/broadcasting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ description: Learn how to broadcast transactions to the Stacks network.

A finalized transaction can be broadcasted to the network or serialized (to a byte representation) using Stacks.js.

```ts
import { bytesToHex } from '@stacks/common';
import {
makeSTXTokenTransfer,
broadcastTransaction,
AnchorMode,
} from '@stacks/transactions';
```ts -n
import { broadcastTransaction, makeSTXTokenTransfer } from "@stacks/transactions";

const broadcastResponse = await broadcastTransaction(transaction);
const txId = broadcastResponse.txid;
const transaction = await makeSTXTokenTransfer({
recipient: "ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5",
amount: 42000000,
senderKey:
"753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601",
network: "devnet",
});

const tx = await broadcastTransaction({ transaction });

const serializedTx = tx.serialize();
const serializedTxHex = bytesToHex(serializedTx);
```

<Callout title="Info">For web applications, user wallets can broadcast transactions via [@stacks/connect](/stacks/connect).</Callout>
35 changes: 33 additions & 2 deletions content/docs/stacks/stacks.js/concepts/post-conditions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ More precisely, adding post-conditions to a transaction can ensure that:
Post-conditions aren't perfect. They can't say anything about the end-state after a transaction. In other words, they can't guarantee the receipt of FTs/NFTs, since they only check for sending.
</Callout>

Here's an example of a post-condition where the `principal` must send 1000 uSTX, or else the transaction will abort:
Here's an example of a post-condition using the `Pc` helper, where the `principal` must send 1000 uSTX, or else the transaction will abort:

```js
```ts -n
import { Pc } from '@stacks/transactions';

const tx = await makeContractCall({
Expand All @@ -28,6 +28,37 @@ const tx = await makeContractCall({
});
```

If you prefer to write the post-condition manually, you can do so using the following approach:

```ts -n
import { StxPostCondition, FungiblePostCondition, NonFungiblePostCondition } from '@stacks/transactions';
// STX post-condition
const stxPostCondition: StxPostCondition = {
type: 'stx-postcondition',
address: 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B',
condition: 'gte', // 'eq' | 'gt' | 'gte' | 'lt' | 'lte'
amount: '100',
};

// Fungible token post-condition
const ftPostCondition: FungiblePostCondition = {
type: 'ft-postcondition',
address: 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B',
condition: 'eq', // 'eq' | 'gt' | 'gte' | 'lt' | 'lte'
amount: '100',
asset: 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.my-ft-token::my-token',
};

// Non-fungible token post-condition
const nftPostCondition: NonFungiblePostCondition = {
type: 'nft-postcondition',
address: 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B',
condition: 'sent', // 'sent' | 'not-sent'
asset: 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.my-nft::my-asset',
assetId: Cl.uint(602),
};
```

## Post-condition mode

In addition to the post-condition itself, we can also specify a `mode` for the transaction to verify asset transfers.
Expand Down
38 changes: 18 additions & 20 deletions content/docs/stacks/stacks.js/concepts/private-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Developers can build scripts, backends, and tools intended for full control over
Let's start by generating a random private key.
Note that this will return a different value each time you run the code.

```ts
```ts -n
import { randomPrivateKey } from '@stacks/transactions';

const privateKey = randomPrivateKey();
Expand All @@ -46,7 +46,7 @@ Typically, we don't want to generate random private keys, but instead use a dete

#### Generate a random seed phrase (24 words):

```ts
```ts -n
import { randomSeedPhrase } from '@stacks/wallet-sdk';

const phrase = randomSeedPhrase();
Expand All @@ -55,11 +55,13 @@ const phrase = randomSeedPhrase();

#### Generate a wallet from a seed phrase:

```ts
import { generateWallet } from '@stacks/wallet-sdk';
```ts -n
import { generateWallet, randomSeedPhrase } from '@stacks/wallet-sdk';

let wallet = generateWallet({
secretKey: seed,
const seedPhrase = randomSeedPhrase();

let wallet = await generateWallet({
secretKey: seedPhrase,
password: "secret",
});

Expand All @@ -75,20 +77,16 @@ console.log(wallet.accounts[0]); // one account is generated by default

#### Generate more accounts:

```ts
import { generateNewAccount } from '@stacks/wallet-sdk';

wallet = generateNewAccount(wallet);
console.log(wallet.accounts.length); // 2
```
```ts -n
import { generateNewAccount, generateWallet, randomSeedPhrase } from '@stacks/wallet-sdk';

### What else can we do with private keys?
const seedPhrase = randomSeedPhrase();

<SmallCard
icon={<FileSignature className='transition-colors duration-500 ease-in-out group-hover:text-primary' />}
href="/stacks/stacks.js/guides/broadcast-transactions"
title="Sign Transactions"
description="Learn how to sign transactions with Stacks.js."
/>
let wallet = await generateWallet({
secretKey: seedPhrase,
password: "secret",
});

{/* todo: add more links and guides: 1. encrypt/decrypt data, 2. create/verify signatures */}
wallet = generateNewAccount(wallet);
console.log(wallet.accounts.length); // 2
```
10 changes: 3 additions & 7 deletions content/docs/stacks/stacks.js/concepts/transactions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ The following shows how to create a simple transaction (STX transfer) using Stac

### Using Stacks Connect

```ts
```ts -n
import { openSTXTransfer } from '@stacks/connect';
import { AnchorMode } from '@stacks/transactions';

openSTXTransfer({
network: 'testnet',

recipient: 'ST39MJ145BR6S8C315AG2BD61SJ16E208P1FDK3AK', // which address you are sending to
amount: 10000, // tokens, denominated in micro-STX
anchorMode: AnchorMode.Any,

onFinish: response => console.log(response.txid),
onCancel: () => console.log('User canceled'),
Expand All @@ -30,16 +28,16 @@ openSTXTransfer({
For full manual transaction signing, you need to provide the sender's private key.
Treat the private key as a secret and *never* expose it to the public.

```ts
```ts -n
import { makeSTXTokenTransfer } from '@stacks/transactions';

const privateKey = randomPrivateKey(); // see "Private Keys & Wallets" page

const tx = await makeSTXTokenTransfer({
recipient: 'ST39MJ145BR6S8C315AG2BD61SJ16E208P1FDK3AK', // which address you are sending to
amount: 10000, // tokens, denominated in micro-STX
anchorMode: 'any',
senderKey: privateKey,
network: "testnet",
});
```

Expand All @@ -49,5 +47,3 @@ In Stacks.js, we can create transactions for different purposes:
- STX token transfers
- Smart contract calls
- Smart contract deployments

{/* continue */}
63 changes: 26 additions & 37 deletions content/docs/stacks/stacks.js/guides/broadcast-transactions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,15 @@ There are three types of transactions:
<TabsContent value="transfer">
To transfer STX, use the `makeSTXTokenTransfer` function provided by the `@stacks/transactions` package:

```ts stx-transfer.ts
import { AnchorMode, makeSTXTokenTransfer, broadcastTransaction } from "@stacks/transactions";
import { StacksDevnet } from "@stacks/network";
```ts stx-transfer.ts -cn
import { broadcastTransaction, makeSTXTokenTransfer } from "@stacks/transactions";

const transaction = await makeSTXTokenTransfer({
recipient: "SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159",
amount: 12345n,
senderKey:
"753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601",
network: new StacksDevnet(),
anchorMode: AnchorMode.Any,
network: "devnet",
});
```

Expand All @@ -80,17 +78,15 @@ There are three types of transactions:
<TabsContent value="deploy">
To deploy a contract, use the `makeContractDeploy` function provided by the `@stacks/transactions` package:

```ts contract-deploy.ts
import { makeContractDeploy, broadcastTransaction, AnchorMode } from '@stacks/transactions';
import { StacksTestnet, StacksMainnet } from '@stacks/network';
```ts contract-deploy.ts -cn
import { broadcastTransaction, makeContractDeploy } from '@stacks/transactions';

const transaction = await makeContractDeploy({
contractName: 'hello-world',
codeBody: `(define-public (hello)
(ok "Hello, world!"))`,
senderKey: '753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601',
network: new StacksTestnet(),
anchorMode: AnchorMode.Any,
network: "testnet",
});
```

Expand All @@ -102,36 +98,29 @@ There are three types of transactions:
<TabsContent value="execute">
To execute a contract function, use the `makeContractCall` function provided by the `@stacks/transactions` package:

```ts function-call.ts
```ts function-call.ts -cn
import {
makeContractCall,
broadcastTransaction,
AnchorMode,
FungibleConditionCode,
makeStandardSTXPostCondition,
bufferCVFromString,
} from '@stacks/transactions';
import { StacksTestnet, StacksMainnet } from '@stacks/network';

// Add an optional post condition
// See below for details on constructing post conditions
const postConditionAddress = 'SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE';
const postConditionCode = FungibleConditionCode.GreaterEqual;
const postConditionAmount = 1000000n;
const postConditions = [
makeStandardSTXPostCondition(postConditionAddress, postConditionCode, postConditionAmount),
];
Cl,
makeContractCall,
Pc,
} from "@stacks/transactions";

const postCondition = Pc.principal("SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE")
.willSendEq(1000000n)
.ustx();

const transaction = await makeContractCall({
contractAddress: 'SPBMRFRPPGCDE3F384WCJPK8PQJGZ8K9QKK7F59X',
contractName: 'contract_name',
functionName: 'contract_function',
functionArgs: [bufferCVFromString('foo')],
senderKey: 'b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01',
contractAddress: "SPBMRFRPPGCDE3F384WCJPK8PQJGZ8K9QKK7F59X",
contractName: "contract_name",
functionName: "contract_function",
functionArgs: [Cl.bufferFromAscii("foo")],
senderKey:
"b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01",
validateWithAbi: true,
network: new StacksTestnet(),
postConditions,
anchorMode: AnchorMode.Any,
network: "testnet",
postConditions: [postCondition],
});
```

Expand All @@ -149,10 +138,10 @@ After building the transaction, broadcast it to the Stacks blockchain network us
1. Pass in the transaction object you created in the previous step to the `broadcastTransaction` function.
2. Handle the response by logging the response object.

```tsx
```ts -cn
import { broadcastTransaction } from '@stacks/transactions';

const broadcastResponse = await broadcastTransaction(transaction);
const broadcastResponse = await broadcastTransaction({ transaction });
```

This code sends the signed transaction to the Stacks blockchain. The `broadcastTransaction` function returns a response containing the transaction ID, which can be used to track the transaction on the blockchain.
Expand All @@ -161,7 +150,7 @@ This code sends the signed transaction to the Stacks blockchain. The `broadcastT

Handle the transaction results by checking the transaction status and responding accordingly.

```ts
```ts -cn
if (broadcastResponse.success) {
console.log('Transaction successful with ID:', broadcastResponse.txid);
} else {
Expand Down
12 changes: 6 additions & 6 deletions content/docs/stacks/stacks.js/guides/post-conditions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Post-conditions can be added to contract calls and FT/NFT transfers to ensure as

For instance, the following post-condition ensures that the principal initiating the transaction must send exactly 1000 uSTX, or else the transaction will abort.

```ts
```ts -cn
import { Pc } from '@stacks/transactions';

const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6')
Expand Down Expand Up @@ -72,7 +72,7 @@ const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6')

When creating a transaction, the mode of the transaction can be set to `Allow` or `Deny` to specify whether unspecified asset transfers are permitted.

```ts
```ts -n
import { PostConditionMode } from '@stacks/transactions';

const tx = await makeContractCall({
Expand All @@ -92,7 +92,7 @@ Essentially, the `postConditionMode` is what tells the Stacks node whether to re

Construct a post-condition for a certain amount of uSTX to be sent.

```ts
```ts -cn
import { Pc } from '@stacks/transactions';

const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6')
Expand All @@ -104,7 +104,7 @@ const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6')

Construct a post-condition for a certain amount of a specific FT to be sent.

```ts
```ts -cn
import { Pc } from '@stacks/transactions';

const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.token-ft')
Expand All @@ -116,7 +116,7 @@ const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.tok

Construct a post-condition for sending / not-sending a specific NFT.

```ts
```ts -cn
import { Pc } from '@stacks/transactions';

const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6')
Expand All @@ -128,7 +128,7 @@ const postCondition = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6')

Construct a post-condition for sending / not-sending a specific SFT (Semi-fungible token).

```ts
```ts -cn
import { Cl, Pc } from '@stacks/transactions';

const postConditionForNFT = Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6')
Expand Down
Loading

0 comments on commit 897c261

Please sign in to comment.