-
Notifications
You must be signed in to change notification settings - Fork 210
/
Copy pathutils.ts
171 lines (143 loc) · 4.59 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import fs from 'fs';
import path from 'path';
import { Buffer } from 'buffer';
import algosdk from '../src';
export async function compileProgram(
client: algosdk.Algodv2,
programSource: string
) {
const compileResponse = await client.compile(Buffer.from(programSource)).do();
const compiledBytes = new Uint8Array(
Buffer.from(compileResponse.result, 'base64')
);
return compiledBytes;
}
export function getLocalKmdClient() {
const kmdToken = 'a'.repeat(64);
const kmdServer = 'http://localhost';
const kmdPort = process.env.KMD_PORT || '4002';
const kmdClient = new algosdk.Kmd(kmdToken, kmdServer, kmdPort);
return kmdClient;
}
export function getLocalIndexerClient() {
const indexerToken = 'a'.repeat(64);
const indexerServer = 'http://localhost';
const indexerPort = process.env.INDEXER_PORT || '8980';
const indexerClient = new algosdk.Indexer(
indexerToken,
indexerServer,
indexerPort
);
return indexerClient;
}
export function getLocalAlgodClient() {
const algodToken = 'a'.repeat(64);
const algodServer = 'http://localhost';
const algodPort = process.env.ALGOD_PORT || '4001';
const algodClient = new algosdk.Algodv2(algodToken, algodServer, algodPort);
return algodClient;
}
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export async function indexerWaitForRound(
client: algosdk.Indexer,
round: number | bigint,
maxAttempts: number
) {
let indexerRound = 0;
let attempts = 0;
for (;;) {
// eslint-disable-next-line no-await-in-loop
const status = await client.makeHealthCheck().do();
indexerRound = status.round;
if (indexerRound >= round) {
// Success
break;
}
// eslint-disable-next-line no-await-in-loop
await sleep(1000); // Sleep 1 second and check again
attempts += 1;
if (attempts > maxAttempts) {
// Failsafe to prevent infinite loop
throw new Error(
`Timeout waiting for indexer to catch up to round ${round}. It is currently on ${indexerRound}`
);
}
}
}
export interface SandboxAccount {
addr: string;
privateKey: Uint8Array;
signer: algosdk.TransactionSigner;
}
export async function getLocalAccounts(): Promise<SandboxAccount[]> {
const kmdClient = getLocalKmdClient();
const wallets = await kmdClient.listWallets();
let walletId;
// eslint-disable-next-line no-restricted-syntax
for (const wallet of wallets.wallets) {
if (wallet.name === 'unencrypted-default-wallet') walletId = wallet.id;
}
if (walletId === undefined)
throw Error('No wallet named: unencrypted-default-wallet');
const handleResp = await kmdClient.initWalletHandle(walletId, '');
const handle = handleResp.wallet_handle_token;
const addresses = await kmdClient.listKeys(handle);
// eslint-disable-next-line camelcase
const acctPromises: Promise<{ private_key: Buffer }>[] = [];
// eslint-disable-next-line no-restricted-syntax
for (const addr of addresses.addresses) {
acctPromises.push(kmdClient.exportKey(handle, '', addr));
}
const keys = await Promise.all(acctPromises);
// Don't need to wait for it
kmdClient.releaseWalletHandle(handle);
return keys.map((k) => {
const addr = algosdk.encodeAddress(k.private_key.slice(32));
const acct = { sk: k.private_key, addr } as algosdk.Account;
const signer = algosdk.makeBasicAccountTransactionSigner(acct);
return {
addr: acct.addr,
privateKey: acct.sk,
signer,
};
});
}
export async function deployCalculatorApp(
algodClient: algosdk.Algodv2,
creator: SandboxAccount
): Promise<number> {
const approvalProgram = fs.readFileSync(
path.join(__dirname, '/calculator/approval.teal'),
'utf8'
);
const clearProgram = fs.readFileSync(
path.join(__dirname, '/calculator/clear.teal'),
'utf8'
);
const approvalBin = await compileProgram(algodClient, approvalProgram);
const clearBin = await compileProgram(algodClient, clearProgram);
const suggestedParams = await algodClient.getTransactionParams().do();
const appCreateTxn = algosdk.makeApplicationCreateTxnFromObject({
from: creator.addr,
approvalProgram: approvalBin,
clearProgram: clearBin,
numGlobalByteSlices: 0,
numGlobalInts: 0,
numLocalByteSlices: 0,
numLocalInts: 0,
suggestedParams,
onComplete: algosdk.OnApplicationComplete.NoOpOC,
});
await algodClient
.sendRawTransaction(appCreateTxn.signTxn(creator.privateKey))
.do();
const result = await algosdk.waitForConfirmation(
algodClient,
appCreateTxn.txID().toString(),
3
);
const appId = result['application-index'];
return appId;
}