Skip to content

Commit

Permalink
chore: update clarity and clarity-wasm (#1372)
Browse files Browse the repository at this point in the history
* chore: update clarity

* chore: update chainhook dependencies

* fix: tests

* feat: update wsts

* feat: update wsts

* refadctor: less unwrap and more expect

* refactor: fix new clippy warning

* chore: use the main branch for clar2wasm

* address review
  • Loading branch information
hugocaillard authored Mar 8, 2024
1 parent 6550640 commit ae47f28
Show file tree
Hide file tree
Showing 20 changed files with 587 additions and 147 deletions.
239 changes: 160 additions & 79 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion components/clarinet-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ansi_term = "0.12.1"
clap = { version = "4.4.8", features = ["derive"], optional = true }
clap_complete = { version = "4.4.4", optional = true }
toml = { version = "0.5.6", features = ["preserve_order"] }
serde = { version = "1.0.136", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1.0.79", features = ["preserve_order"] }
serde_derive = "1"
log = { version = "=0.4.17", features = ["serde"] }
Expand Down
2 changes: 1 addition & 1 deletion components/clarinet-files/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ edition = "2021"
serde = "1"
serde_derive = "1"
# chainhook-types = "1.2"
chainhook-types = { version = "1.2", git = "https://github.com/hirosystems/chainhook.git", rev="ac59025" }
chainhook-types = { version = "1.2", git = "https://github.com/hirosystems/chainhook.git", branch="chore/update-clarinet-and-clarity" }
bip39 = { version = "1.0.1", default-features = false }
libsecp256k1 = "0.7.0"
toml = { version = "0.5.6", features = ["preserve_order"] }
Expand Down
3 changes: 2 additions & 1 deletion components/clarinet-sdk-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ path = "src/lib.rs"
console_error_panic_hook = { version = "0.1", optional = true }
gloo-utils = { version = "0.2", features = ["serde"] }
js-sys = { version = "0.3", optional = true }
serde = { version = "1.0.136", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1.0"
serde-wasm-bindgen = { version = "0.6.4", optional = true }
wasm-bindgen = { version = "0.2.91", optional = true }
wasm-bindgen-futures = { version = "0.4.41", optional = true }
web-sys = { version = "0.3", features = ["console"], optional = true }
colored = "2.1.0"
hashbrown = { version = "0.14.3", features = ["serde"]}

clarinet-files = { path = "../clarinet-files", default-features = false }
clarity-repl = { path = "../clarity-repl", default-features = false, optional = true }
Expand Down
16 changes: 12 additions & 4 deletions components/clarinet-sdk-wasm/src/utils/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ pub fn serialize_event(event: &StacksTransactionEvent) -> StacksEvent {
match event {
StacksTransactionEvent::SmartContractEvent(data) => StacksEvent {
event: "print_event".into(),
data: data.json_serialize(),
data: data
.json_serialize()
.expect("failed to serialize smart contract event"),
},
StacksTransactionEvent::STXEvent(STXEventType::STXTransferEvent(data)) => StacksEvent {
event: "stx_transfer_event".into(),
Expand All @@ -49,15 +51,21 @@ pub fn serialize_event(event: &StacksTransactionEvent) -> StacksEvent {
},
StacksTransactionEvent::NFTEvent(NFTEventType::NFTTransferEvent(data)) => StacksEvent {
event: "nft_transfer_event".into(),
data: data.json_serialize(),
data: data
.json_serialize()
.expect("failed to serialize nft transfer event"),
},
StacksTransactionEvent::NFTEvent(NFTEventType::NFTMintEvent(data)) => StacksEvent {
event: "nft_mint_event".into(),
data: data.json_serialize(),
data: data
.json_serialize()
.expect("failed to serialize nft mint event"),
},
StacksTransactionEvent::NFTEvent(NFTEventType::NFTBurnEvent(data)) => StacksEvent {
event: "nft_burn_event".into(),
data: data.json_serialize(),
data: data
.json_serialize()
.expect("failed to serialize nft burn event"),
},
StacksTransactionEvent::FTEvent(FTEventType::FTTransferEvent(data)) => StacksEvent {
event: "ft_transfer_event".into(),
Expand Down
240 changes: 240 additions & 0 deletions components/clarinet-sdk/tests/pox-locking.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import crypto from "crypto";
import { describe, expect, it, beforeEach } from "vitest";

import { Pox4SignatureTopic, StackingClient, poxAddressToTuple } from "@stacks/stacking";
import { StacksDevnet } from "@stacks/network";
import { getPublicKeyFromPrivate, publicKeyToBtcAddress } from "@stacks/encryption";
import {
Cl,
ClarityType,
getAddressFromPrivateKey,
TransactionVersion,
createStacksPrivateKey,
} from "@stacks/transactions";

// test the built package and not the source code
// makes it simpler to handle wasm build
import { Simnet, initSimnet } from "../dist/esm";

const MAX_U128 = 340282366920938463463374607431768211455n;
const maxAmount = MAX_U128;

const randInt = () => crypto.randomInt(0, 0xffffffffffff);

const address1 = "ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5";
const address2 = "ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG";
const poxDeployer = "ST000000000000000000002AMW42H";

let simnet: Simnet;

const initialSTXBalance = 100_000_000 * 1e6;

describe("test pox-3", () => {
const poxContract = `${poxDeployer}.pox-3`;
beforeEach(async () => {
simnet = await initSimnet("tests/fixtures/Clarinet.toml");
simnet.setEpoch("2.4");
});

const ustxAmount = initialSTXBalance * 0.9; // lock 90% of the initial balance

it("can transfer-stx", () => {
// safe check that address1 can transfer 90% of its balance if not locked
const transfer = simnet.transferSTX(ustxAmount, address2, address1);
expect(transfer.result).toStrictEqual(Cl.ok(Cl.bool(true)));
});

it("can call is-pox-active", () => {
const isPoxActive = simnet.callReadOnlyFn(
poxContract,
"is-pox-active",
[Cl.uint(100)],
address1,
);
expect(isPoxActive.result).toStrictEqual(Cl.bool(true));
});

it("can stack-stx on pox-3", () => {
const stackStxArgs = [
Cl.uint(ustxAmount),
Cl.tuple({
version: Cl.bufferFromHex("00"),
hashbytes: Cl.bufferFromHex("7321b74e2b6a7e949e6c4ad313035b1665095017"),
}),
Cl.uint(0),
Cl.uint(1),
];
const stackStx = simnet.callPublicFn(poxContract, "stack-stx", stackStxArgs, address1);
expect(stackStx.events).toHaveLength(2);
expect(stackStx.result).toStrictEqual(
Cl.ok(
Cl.tuple({
"lock-amount": Cl.uint(ustxAmount),
"unlock-burn-height": Cl.uint(2100),
stacker: Cl.principal(address1),
}),
),
);

const stxAccount = simnet.runSnippet(`(stx-account '${address1})`);
expect(stxAccount).toStrictEqual(
Cl.tuple({
locked: Cl.uint(ustxAmount),
unlocked: Cl.uint(initialSTXBalance - ustxAmount),
"unlock-height": Cl.uint(2100),
}),
);

const transfer = simnet.transferSTX(ustxAmount, address2, address1);
expect(transfer.result).toStrictEqual(Cl.error(Cl.uint(1)));
});

it("unlocks stx after a certain number of blocks", () => {
const stackStxArgs = [
Cl.uint(ustxAmount),
Cl.tuple({
version: Cl.bufferFromHex("00"),
hashbytes: Cl.bufferFromHex("7321b74e2b6a7e949e6c4ad313035b1665095017"),
}),
Cl.uint(0),
Cl.uint(1),
];
simnet.callPublicFn(poxContract, "stack-stx", stackStxArgs, address1);

simnet.mineEmptyBlocks(2098);
const stxAccountBefore = simnet.runSnippet(`(stx-account '${address1})`);
expect(stxAccountBefore).toStrictEqual(
Cl.tuple({
locked: Cl.uint(ustxAmount),
unlocked: Cl.uint(initialSTXBalance - ustxAmount),
"unlock-height": Cl.uint(2100),
}),
);

simnet.mineEmptyBlocks(1);
const stxAccountAfter = simnet.runSnippet(`(stx-account '${address1})`);
expect(stxAccountAfter).toStrictEqual(
Cl.tuple({
locked: Cl.uint(0),
unlocked: Cl.uint(initialSTXBalance),
"unlock-height": Cl.uint(0),
}),
);
});
});

describe("test pox-4", () => {
const poxContract = `${poxDeployer}.pox-4`;

// wallet_1, wallet_2, wallet_3 private keys
const stackingKeys = [
"7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801",
"530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101",
];

const accounts = stackingKeys.map((privKey) => {
const network = new StacksDevnet();

const pubKey = getPublicKeyFromPrivate(privKey);
const stxAddress = getAddressFromPrivateKey(privKey, TransactionVersion.Testnet);
const signerPrivKey = createStacksPrivateKey(privKey);
const signerPubKey = getPublicKeyFromPrivate(signerPrivKey.data);

return {
privKey,
pubKey,
stxAddress,
btcAddr: publicKeyToBtcAddress(pubKey),
signerPrivKey: signerPrivKey,
signerPubKey: signerPubKey,
client: new StackingClient(stxAddress, {
...network,
transactionVersion: network.version,
magicBytes: "X2",
peerNetworkId: network.chainId,
}),
};
});

const stackingThreshold = 50000000000;

beforeEach(async () => {
simnet = await initSimnet("tests/fixtures/Clarinet.toml");
simnet.setEpoch("3.0");
});

it("can call get-pox-info", async () => {
const poxInfo = simnet.callReadOnlyFn(poxContract, "get-pox-info", [], address1);
expect(poxInfo.result.type).toBe(ClarityType.ResponseOk);
});

it("can call get-pox-info", async () => {
const account = accounts[0];
const rewardCycle = 0;
const burnBlockHeight = 0;
const period = 1;
const authId = randInt();
const poxInfo = simnet.callReadOnlyFn(poxContract, "get-pox-info", [], address1);

expect(poxInfo.result.type).toBe(ClarityType.ResponseOk);

expect(poxInfo.result).toHaveProperty("value.data.min-amount-ustx", Cl.uint(stackingThreshold));
expect(poxInfo.result).toHaveProperty("value.data.reward-cycle-id", Cl.uint(rewardCycle));

const sigArgs = {
authId,
maxAmount,
rewardCycle,
period,
topic: Pox4SignatureTopic.StackStx,
poxAddress: account.btcAddr,
signerPrivateKey: account.signerPrivKey,
};
const signerSignature = account.client.signPoxSignature(sigArgs);
const ustxAmount = Math.floor(stackingThreshold * 1.5);

/*
(stack-stx (amount-ustx uint)
(pox-addr (tuple (version (buff 1)) (hashbytes (buff 32))))
(start-burn-ht uint)
(lock-period uint)
(signer-sig (optional (buff 65)))
(signer-key (buff 33))
(max-amount uint)
(auth-id uint))
*/

const stackStxArgs = [
Cl.uint(ustxAmount),
poxAddressToTuple(account.btcAddr),
Cl.uint(burnBlockHeight),
Cl.uint(period),
Cl.some(Cl.bufferFromHex(signerSignature)),
Cl.bufferFromHex(account.signerPubKey),
Cl.uint(maxAmount),
Cl.uint(authId),
];

const stackStx = simnet.callPublicFn(poxContract, "stack-stx", stackStxArgs, address1);

expect(stackStx.result).toStrictEqual(
Cl.ok(
Cl.tuple({
"lock-amount": Cl.uint(75000000000),
"signer-key": Cl.bufferFromHex(account.signerPubKey),
stacker: Cl.principal(address1),
"unlock-burn-height": Cl.uint(2100),
}),
),
);

const stxAccount = simnet.runSnippet(`(stx-account '${address1})`);
expect(stxAccount).toStrictEqual(
Cl.tuple({
locked: Cl.uint(ustxAmount),
unlocked: Cl.uint(initialSTXBalance - ustxAmount),
"unlock-height": Cl.uint(2100),
}),
);
});
});
2 changes: 1 addition & 1 deletion components/clarity-events/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ clarinet-files = { path = "../clarinet-files", default-features = false, optiona
clarity-repl = { path = "../clarity-repl", default-features = false }
clap = { version = "4.4.8", features = ["derive"], optional = true }
toml = { version = "0.5.6", features = ["preserve_order"], optional = true }
serde = { version = "1.0.136", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1.0.79", features = ["preserve_order"] }
serde_derive = "1"

Expand Down
Loading

0 comments on commit ae47f28

Please sign in to comment.