Skip to content

Commit 082515c

Browse files
Merge pull request #146 from stacks-network/fix/sbtc-balances-restore
Fix type mismatch in sBTC balance restore feature
2 parents b857078 + 33ac7e4 commit 082515c

File tree

2 files changed

+71
-21
lines changed

2 files changed

+71
-21
lines changed

citizen.tests.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fc from "fast-check";
22
import {
33
buildRendezvousData,
44
getContractSource,
5+
getSbtcBalancesFromSimnet,
56
getTestContractSource,
67
groupContractsByEpochFromSimnetPlan,
78
issueFirstClassCitizenship,
@@ -366,7 +367,7 @@ describe("Simnet deployment plan operations", () => {
366367
rmSync(tempDir, { recursive: true, force: true });
367368
});
368369

369-
it(`the first-class citizenship simnet has the correct balances for the registered accounts`, async () => {
370+
it(`the first-class citizenship simnet has the correct STX balances for the registered accounts`, async () => {
370371
// Setup
371372
const tempDir = mkdtempSync(join(tmpdir(), "simnet-test-"));
372373
cpSync(manifestDir, tempDir, { recursive: true });
@@ -399,4 +400,35 @@ describe("Simnet deployment plan operations", () => {
399400
// Teardown
400401
rmSync(tempDir, { recursive: true, force: true });
401402
});
403+
404+
it(`the first-class citizenship simnet has the correct sBTC balances for the registered accounts`, async () => {
405+
// Setup
406+
const tempDir = mkdtempSync(join(tmpdir(), "simnet-test-"));
407+
cpSync(manifestDir, tempDir, { recursive: true });
408+
409+
// Exercise
410+
const firstClassSimnet = await issueFirstClassCitizenship(
411+
tempDir,
412+
join(tempDir, getManifestFileName(tempDir, "counter")),
413+
tryParseRemoteDataSettings(
414+
join(manifestDir, "Clarinet.toml"),
415+
new EventEmitter()
416+
),
417+
"counter"
418+
);
419+
420+
// Verify
421+
const sbtcBalancesMap = getSbtcBalancesFromSimnet(firstClassSimnet);
422+
423+
// The expected balance is 0 (number) for all accounts, since the example
424+
// Clarinet project does not operate with sBTC.
425+
const numAccounts = firstClassSimnet.getAccounts().size;
426+
const numZeroBalanceAccounts = Array.from(sbtcBalancesMap.values()).filter(
427+
(balance) => balance === 0
428+
).length;
429+
expect(numZeroBalanceAccounts).toBe(numAccounts);
430+
431+
// Teardown
432+
rmSync(tempDir, { recursive: true, force: true });
433+
});
402434
});

citizen.ts

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,26 +65,7 @@ export const issueFirstClassCitizenship = async (
6565
})
6666
);
6767

68-
const sbtcBalancesMap = new Map(
69-
simnetAddresses.map((address) => {
70-
try {
71-
const { result: getBalanceResult } = simnet.callReadOnlyFn(
72-
"SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token",
73-
"get-balance",
74-
[Cl.principal(address)],
75-
address
76-
);
77-
78-
// If the previous read-only call works, the user is working with
79-
// sBTC. This means we can proceed with restoring sBTC balances.
80-
const sbtcBalance = cvToJSON(getBalanceResult).value.value;
81-
82-
return [address, sbtcBalance];
83-
} catch (e) {
84-
return [address, 0];
85-
}
86-
})
87-
);
68+
const sbtcBalancesMap = getSbtcBalancesFromSimnet(simnet);
8869

8970
await simnet.initEmptySession(remoteDataSettings);
9071

@@ -386,6 +367,43 @@ export function scheduleRendezvous(
386367
return `${targetContractSource}\n\n${context}\n\n${tests}`;
387368
}
388369

370+
/**
371+
* Maps the simnet accounts to their sBTC balances. The function tries to call
372+
* the `get-balance` function of the `sbtc-token` contract for each address. If
373+
* the call fails, it returns a balance of 0 for that address. The call fails
374+
* if the user is not working with sBTC.
375+
* @param simnet The simnet instance.
376+
* @returns A map of addresses to their sBTC balances.
377+
*/
378+
export const getSbtcBalancesFromSimnet = (
379+
simnet: Simnet
380+
): Map<string, number> =>
381+
new Map(
382+
[...simnet.getAccounts().values()].map((address) => {
383+
try {
384+
const { result: getBalanceResult } = simnet.callReadOnlyFn(
385+
"SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token",
386+
"get-balance",
387+
[Cl.principal(address)],
388+
address
389+
);
390+
391+
// If the previous read-only call works, the user is working with
392+
// sBTC. This means we can proceed with restoring sBTC balances.
393+
const sbtcBalanceJSON = cvToJSON(getBalanceResult);
394+
395+
// The `get-balance` function returns a response containing the uint
396+
// balance of the address. In the JSON representation, the balance is
397+
// represented as a string. We need to parse it to an integer.
398+
const sbtcBalance = parseInt(sbtcBalanceJSON.value.value, 10);
399+
400+
return [address, sbtcBalance];
401+
} catch (e) {
402+
return [address, 0];
403+
}
404+
})
405+
);
406+
389407
/**
390408
* Utility function that restores the test wallets' initial sBTC balances in
391409
* the re-initialized first-class citizenship simnet.

0 commit comments

Comments
 (0)