Skip to content
This repository was archived by the owner on Feb 11, 2025. It is now read-only.

Commit 585a386

Browse files
committed
fix: 429 error
1 parent a6de240 commit 585a386

File tree

8 files changed

+170
-58
lines changed

8 files changed

+170
-58
lines changed

actions/transferAll/core.ts

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
import { BigNumber, utils } from "ethers";
2-
import {
3-
Account as SNAccount,
4-
ec,
5-
number,
6-
SequencerProvider,
7-
uint256,
8-
} from "starknet";
2+
import { number, uint256 } from "starknet";
93
import { compileCalldata } from "starknet/dist/utils/stark";
104
import { Account } from "../../ui/pickAccounts";
115
import TOKENS from "../../default-tokens.json";
126
import { Ora } from "ora";
137
import { oraLog } from "../../oraLog";
148
import { estimateFee, execute } from "../../execute";
9+
import { formatAddress } from "../../addressFormatting";
1510

1611
export async function transferAll(acc: Account, newAddress: string, ora: Ora) {
1712
const { privateKey } = acc;
1813
if (!privateKey) {
1914
throw new Error("No private key for account to credit");
2015
}
2116

22-
const provider = new SequencerProvider({ network: acc.networkId as any });
2317
const tokens = TOKENS.filter((t) => t.network === acc.networkId);
2418
const calls = Object.entries(acc.balances)
2519
.filter(([, balance]) => utils.parseEther(balance).gt(0))
@@ -47,36 +41,44 @@ export async function transferAll(acc: Account, newAddress: string, ora: Ora) {
4741
if (calls.length) {
4842
const { suggestedMaxFee } = await estimateFee(acc, calls);
4943

50-
const callsWithFee = calls.map((c) => {
51-
const tokenDetails = tokens.find((t) => t.symbol === "ETH");
52-
if (c.contractAddress === tokenDetails?.address) {
53-
const balance = acc.balances[c.contractAddress];
54-
return {
55-
...c,
56-
calldata: compileCalldata({
57-
to: newAddress.toLowerCase(),
58-
value: {
59-
type: "struct",
60-
...uint256.bnToUint256(
61-
number.toBN(
62-
utils
63-
.parseUnits(balance, tokenDetails?.decimals ?? 18)
64-
.sub(number.toHex(suggestedMaxFee))
65-
.toString()
66-
)
67-
),
68-
},
69-
}),
70-
};
71-
}
72-
return c;
73-
});
44+
const callsWithFee = calls
45+
.map((c) => {
46+
const tokenDetails = tokens.find((t) => t.symbol === "ETH");
47+
if (c.contractAddress === tokenDetails?.address) {
48+
const balance = acc.balances[c.contractAddress];
49+
const amount = utils
50+
.parseUnits(balance, tokenDetails?.decimals ?? 18)
51+
.sub(number.toHex(suggestedMaxFee));
52+
53+
if (amount.lte(0)) {
54+
ora.info(
55+
`Account ${formatAddress(
56+
acc.address
57+
)} has not enough ETH to do a transfer`
58+
);
59+
return false;
60+
}
61+
62+
return {
63+
...c,
64+
calldata: compileCalldata({
65+
to: newAddress.toLowerCase(),
66+
value: {
67+
type: "struct",
68+
...uint256.bnToUint256(number.toBN(amount.toString())),
69+
},
70+
}),
71+
};
72+
}
73+
return c;
74+
})
75+
.filter(Boolean);
7476

7577
// execute with suggested max fee substracted from a potential eth transfer
7678
const transaction = await execute(acc, callsWithFee);
7779

7880
oraLog(ora, `Transaction ${transaction.transaction_hash} created`);
7981

80-
await provider.waitForTransaction(transaction.transaction_hash);
82+
return transaction.transaction_hash;
8183
}
8284
}

actions/transferAll/ui.ts

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,30 @@ import { ValidationError } from "yup";
44
import { addressSchema } from "../../schema";
55
import { Account } from "../../ui/pickAccounts";
66
import { transferAll } from "./core";
7+
import { SequencerProvider } from "starknet-4220";
8+
9+
type PromiseFactory<T> = () => Promise<T>;
10+
11+
type PromiseResult<T> =
12+
| { status: "fulfilled"; value: T }
13+
| { status: "rejected"; reason: any };
14+
15+
async function allSettled<T>(
16+
promiseFactories: PromiseFactory<T>[]
17+
): Promise<PromiseResult<T>[]> {
18+
const results: PromiseResult<T>[] = [];
19+
20+
for (const promiseFactory of promiseFactories) {
21+
try {
22+
const value = await promiseFactory();
23+
results.push({ status: "fulfilled", value });
24+
} catch (reason) {
25+
results.push({ status: "rejected", reason });
26+
}
27+
}
28+
29+
return results;
30+
}
731

832
export async function showTransferAll(accounts: Account[]) {
933
const { toAddress } = await prompts(
@@ -30,16 +54,32 @@ export async function showTransferAll(accounts: Account[]) {
3054

3155
const spinner = ora("Transfering tokens").start();
3256

33-
const transferResults = await Promise.allSettled(
34-
accounts.map(async (acc) => transferAll(acc, toAddress, spinner))
57+
const transferResults = await allSettled(
58+
accounts.map((acc) => () => transferAll(acc, toAddress, spinner))
3559
);
3660

37-
transferResults.forEach((result) => {
38-
if (result.status === "rejected") {
39-
spinner.fail(result.reason?.toString());
40-
}
61+
const transactions = transferResults
62+
.map((result) => {
63+
if (result.status === "rejected") {
64+
spinner.fail(result.reason?.toString());
65+
return undefined;
66+
}
67+
return result.value;
68+
})
69+
.filter((tx) => !!tx);
70+
71+
const provider = new SequencerProvider({
72+
network: accounts[0].networkId as any,
4173
});
4274

75+
spinner.info(`Waiting for ${transactions.length} transactions`);
76+
await Promise.all(
77+
transactions.map((tx) => {
78+
if (!tx) return;
79+
return provider.waitForTransaction(tx);
80+
})
81+
);
82+
4383
if (transferResults.every((result) => result.status === "fulfilled")) {
4484
spinner.succeed("Transfers complete");
4585
} else if (transferResults.some((result) => result.status === "fulfilled")) {

execute.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
SequencerProvider as NewProvider,
33
Account as NewAccount,
4-
} from "starknet-490";
4+
} from "starknet-4220";
55
import {
66
Call,
77
SequencerProvider as OldProvider,
@@ -10,6 +10,7 @@ import {
1010
} from "starknet";
1111
import { BigNumber } from "ethers";
1212
import { Account } from "./ui/pickAccounts";
13+
import { lte } from "semver";
1314

1415
export async function estimateFee(account: Account, call: Call[] | Call) {
1516
const calls = Array.isArray(call) ? call : [call];
@@ -42,15 +43,35 @@ export async function execute(account: Account, call: Call[] | Call) {
4243
"Account cant be controlled with the selected private key or seed"
4344
);
4445
}
45-
try {
46-
const oldProvider = new OldProvider({ network: account.networkId as any });
47-
const a = new OldAccount(oldProvider, lowerCaseAddress, keyPair);
48-
return await a.execute(calls);
49-
} catch (e) {
50-
const newProvider = new NewProvider({ network: account.networkId as any });
51-
const a = new NewAccount(newProvider, lowerCaseAddress, keyPair);
52-
return a.execute(calls).catch((e) => {
53-
throw e;
54-
});
46+
if (account.version && lte(account.version, "0.2.2")) {
47+
try {
48+
const oldProvider = new OldProvider({
49+
network: account.networkId as any,
50+
});
51+
const a = new OldAccount(oldProvider, lowerCaseAddress, keyPair);
52+
return await a.execute(calls);
53+
} catch (e) {
54+
console.warn("Fallback to new provider", (e as any)?.errorCode);
55+
const newProvider = new NewProvider({
56+
network: account.networkId as any,
57+
});
58+
const a = new NewAccount(newProvider, lowerCaseAddress, keyPair);
59+
return await a.execute(calls);
60+
}
61+
} else {
62+
try {
63+
const newProvider = new NewProvider({
64+
network: account.networkId as any,
65+
});
66+
const a = new NewAccount(newProvider, lowerCaseAddress, keyPair);
67+
return await a.execute(calls);
68+
} catch (e) {
69+
console.warn("Fallback to old provider", (e as any)?.errorCode);
70+
const oldProvider = new OldProvider({
71+
network: account.networkId as any,
72+
});
73+
const a = new OldAccount(oldProvider, lowerCaseAddress, keyPair);
74+
return await a.execute(calls);
75+
}
5576
}
5677
}

fetchPolyfill.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import ora from "ora";
2+
3+
type Fetch = typeof fetch;
4+
5+
const originalFetch: Fetch = fetch.bind(globalThis);
6+
7+
const wait = (ms: number): Promise<void> =>
8+
new Promise((resolve) => setTimeout(resolve, ms));
9+
10+
const customFetch: Fetch = async (input, init): Promise<Response> => {
11+
const response = await originalFetch(input, init);
12+
13+
if (response.status === 429) {
14+
// Wait for one minute before retrying
15+
ora().warn("429 - waiting 1 minute before retrying request");
16+
await wait(60 * 1000);
17+
return originalFetch(input, init);
18+
}
19+
20+
return response;
21+
};
22+
23+
globalThis.fetch = customFetch;

index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#!/usr/bin/env npx ts-node
2+
import "@total-typescript/ts-reset";
3+
import "./fetchPolyfill";
4+
25
import { program } from "commander";
36
import ora from "ora";
47
import { Account, pickAccounts } from "./ui/pickAccounts";

issues/deploy/fix.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
SequencerProvider,
66
stark,
77
hash,
8-
} from "starknet-490";
8+
} from "starknet-4220";
99
import { PROXY_CONTRACT_CLASS_HASHES } from "../../getAccounts";
1010
import { getVersion } from "../../getVersion";
1111
import { oraLog } from "../../oraLog";

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"outputPath": "bin"
2323
},
2424
"devDependencies": {
25+
"@total-typescript/ts-reset": "^0.4.2",
2526
"@types/lodash.chunk": "^4.2.7",
2627
"@types/prompts": "^2.0.14",
2728
"@types/semver": "^7.3.10",
@@ -40,9 +41,9 @@
4041
"ora": "5",
4142
"prompts": "^2.4.2",
4243
"semver": "^7.3.7",
43-
"starknet-490": "npm:[email protected]",
4444
"starknet": "4.1.0",
4545
"starknet-390": "npm:[email protected]",
46+
"starknet-4220": "npm:[email protected]",
4647
"yup": "^1.0.0-beta.4"
4748
}
4849
}

yarn.lock

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,11 @@
577577
"@noble/hashes" "~1.1.1"
578578
"@scure/base" "~1.1.0"
579579

580+
"@total-typescript/ts-reset@^0.4.2":
581+
version "0.4.2"
582+
resolved "https://registry.yarnpkg.com/@total-typescript/ts-reset/-/ts-reset-0.4.2.tgz#c564c173ba09973968e1046c93965b7a257878a4"
583+
integrity sha512-vqd7ZUDSrXFVT1n8b2kc3LnklncDQFPvR58yUS1kEP23/nHPAO9l1lMjUfnPrXYYk4Hj54rrLKMW5ipwk7k09A==
584+
580585
"@tsconfig/node10@^1.0.7":
581586
version "1.0.9"
582587
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
@@ -1905,10 +1910,10 @@ slash@^3.0.0:
19051910
superstruct "^0.15.3"
19061911
url-join "^4.0.1"
19071912

1908-
"starknet-490@npm:starknet@4.9.0", starknet@^4.9.0:
1909-
version "4.9.0"
1910-
resolved "https://registry.yarnpkg.com/starknet/-/starknet-4.9.0.tgz#1d0b5a1ff532a41b84a619f3d7c3f833f67dad2d"
1911-
integrity sha512-0Y9Nce0msMs1k3jid93ZuPD2e3yW42FUuMFChRTaq1qcjP8G/fL+5+/zuq441VQ82/JxAHnVqBMvpmMgn5yJSA==
1913+
"starknet-4220@npm:starknet@4.22.0":
1914+
version "4.22.0"
1915+
resolved "https://registry.yarnpkg.com/starknet/-/starknet-4.22.0.tgz#8d0c628e2a8e868ee9b4757afe89f07b05ec55ff"
1916+
integrity sha512-jC9Taxb6a/ht9zmS1LU/DSLfwJKpgCJnE9AktVksc5SE/+jQMpqxsq6fm7PRiqupjiqRC1DOS8N47cj+KaGv4Q==
19121917
dependencies:
19131918
"@ethersproject/bytes" "^5.6.1"
19141919
bn.js "^5.2.1"
@@ -1919,7 +1924,7 @@ slash@^3.0.0:
19191924
json-bigint "^1.0.0"
19201925
minimalistic-assert "^1.0.1"
19211926
pako "^2.0.4"
1922-
ts-custom-error "^3.2.0"
1927+
ts-custom-error "^3.3.1"
19231928
url-join "^4.0.1"
19241929

19251930
@@ -1939,6 +1944,23 @@ [email protected]:
19391944
ts-custom-error "^3.2.0"
19401945
url-join "^4.0.1"
19411946

1947+
starknet@^4.9.0:
1948+
version "4.9.0"
1949+
resolved "https://registry.yarnpkg.com/starknet/-/starknet-4.9.0.tgz#1d0b5a1ff532a41b84a619f3d7c3f833f67dad2d"
1950+
integrity sha512-0Y9Nce0msMs1k3jid93ZuPD2e3yW42FUuMFChRTaq1qcjP8G/fL+5+/zuq441VQ82/JxAHnVqBMvpmMgn5yJSA==
1951+
dependencies:
1952+
"@ethersproject/bytes" "^5.6.1"
1953+
bn.js "^5.2.1"
1954+
elliptic "^6.5.4"
1955+
ethereum-cryptography "^1.0.3"
1956+
hash.js "^1.1.7"
1957+
isomorphic-fetch "^3.0.0"
1958+
json-bigint "^1.0.0"
1959+
minimalistic-assert "^1.0.1"
1960+
pako "^2.0.4"
1961+
ts-custom-error "^3.2.0"
1962+
url-join "^4.0.1"
1963+
19421964
stream-meter@^1.0.4:
19431965
version "1.0.4"
19441966
resolved "https://registry.yarnpkg.com/stream-meter/-/stream-meter-1.0.4.tgz#52af95aa5ea760a2491716704dbff90f73afdd1d"
@@ -2069,7 +2091,7 @@ tr46@~0.0.3:
20692091
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
20702092
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
20712093

2072-
ts-custom-error@^3.2.0:
2094+
ts-custom-error@^3.2.0, ts-custom-error@^3.3.1:
20732095
version "3.3.1"
20742096
resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1"
20752097
integrity sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==

0 commit comments

Comments
 (0)