starknet 4.13.2 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/CODE_OF_CONDUCT.md +128 -0
  3. package/README.md +2 -2
  4. package/__mocks__/naming_compiled.json +53283 -0
  5. package/__mocks__/starknetId_compiled.json +44703 -0
  6. package/__tests__/account.test.ts +100 -15
  7. package/__tests__/contract.test.ts +70 -57
  8. package/__tests__/defaultProvider.test.ts +14 -13
  9. package/__tests__/fixtures.ts +27 -26
  10. package/__tests__/rpcProvider.test.ts +19 -16
  11. package/__tests__/sequencerProvider.test.ts +47 -55
  12. package/__tests__/utils/starknetId.test.ts +53 -0
  13. package/__tests__/utils/utils.test.ts +10 -0
  14. package/dist/index.d.ts +116 -30
  15. package/dist/index.global.js +660 -463
  16. package/dist/index.global.js.map +1 -1
  17. package/dist/index.js +247 -51
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +247 -51
  20. package/dist/index.mjs.map +1 -1
  21. package/index.d.ts +116 -30
  22. package/index.global.js +660 -463
  23. package/index.global.js.map +1 -1
  24. package/index.js +247 -51
  25. package/index.js.map +1 -1
  26. package/index.mjs +247 -51
  27. package/index.mjs.map +1 -1
  28. package/package.json +3 -3
  29. package/src/account/default.ts +81 -8
  30. package/src/account/interface.ts +71 -5
  31. package/src/contract/contractFactory.ts +20 -13
  32. package/src/contract/default.ts +11 -2
  33. package/src/provider/default.ts +26 -11
  34. package/src/provider/interface.ts +9 -3
  35. package/src/provider/rpc.ts +15 -11
  36. package/src/provider/sequencer.ts +32 -20
  37. package/src/provider/utils.ts +19 -11
  38. package/src/types/account.ts +21 -1
  39. package/src/types/lib.ts +5 -2
  40. package/src/types/provider.ts +0 -5
  41. package/src/utils/events.ts +32 -0
  42. package/src/utils/number.ts +6 -0
  43. package/src/utils/starknetId.ts +116 -0
  44. package/www/docs/API/account.md +176 -2
  45. package/www/docs/API/contractFactory.md +7 -11
  46. package/www/docs/API/provider.md +5 -9
  47. package/www/docs/API/utils.md +8 -0
  48. package/www/guides/account.md +89 -38
  49. package/www/guides/erc20.md +115 -59
  50. package/www/guides/intro.md +11 -4
@@ -136,6 +136,14 @@ Converts BN to hex.
136
136
 
137
137
  Returns a string.
138
138
 
139
+ ### cleanHex
140
+
141
+ `cleanHex(hex: string): string`
142
+
143
+ Remove leading zeroes and lowercase hex string after '0x'
144
+
145
+ `0x01AFF` -> `0x1aff`
146
+
139
147
  ### hexToDecimalString
140
148
 
141
149
  `hexToDecimalString(hex: string): string`
@@ -8,9 +8,22 @@ Since there are no Externally Owned Accounts (EOA) in StarkNet, all Accounts in
8
8
 
9
9
  Unlike in Ethereum where a wallet is created with a public and private key pair, StarkNet Accounts are the only way to sign transactions and messages, and verify signatures. Therefore a Account - Contract interface is needed.
10
10
 
11
- ## Install and import StarkNet
11
+ > Account contracts on StarkNet cannot be deployed without paying a fee.
12
12
 
13
- Install the latest version of starknet with `npm install starknet@next`
13
+ High level explanations from StarkWare can be found in this Notion [page](https://starkware.notion.site/Deploy-a-contract-and-an-account-on-StarkNet-ed2fd13301d2414e8223bb72bb90e386), but in short, the process is:
14
+
15
+ 1. Decide on your account type (OpenZeppelin, Argent, ...)
16
+ 2. Compute the address of our would-be account off-chain (adressess on StarkNet are deterministic)
17
+ 3. Send funds to this pre-computed address. The funds will be used to pay for the account contract deployment
18
+ 4. Actual deployment of the Account
19
+
20
+ ## Install and setup
21
+
22
+ Install the latest version of starknet with
23
+
24
+ `npm install starknet@next`
25
+
26
+ Imports example:
14
27
 
15
28
  ```javascript
16
29
  import fs from "fs";
@@ -21,69 +34,107 @@ import {
21
34
  ec,
22
35
  json,
23
36
  number,
37
+ hash
24
38
  } from "starknet";
25
39
  ```
26
40
 
27
- ## Generate random key pair.
41
+ Starknet.js currently doesn't have the functionality to calculate the class hash needed for the account deployment, so we need to calculate it with some other tool, for example: [Starkli](https://github.com/xJonathanLEI/starkli)
42
+
43
+ ```javascript
44
+ // class hash of OpenZeppelin Account contract version 0.5.1
45
+ const OZContractClassHash = '0x058d97f7d76e78f44905cc30cb65b91ea49a4b908a76703c54197bca90f81773';
46
+ ```
47
+
48
+ ```javascript
49
+ // get the compiled contract ABI, in this case OpenZeppelin
50
+ const compiledOZAccount = json.parse(
51
+ fs.readFileSync("./Account.json").toString("ascii")
52
+ );
53
+ ```
28
54
 
29
- You can also get a key pair from a private key using `getKeyPair(pk: BigNumberish)`
55
+ ## Generate random key pair
30
56
 
31
57
  ```javascript
32
58
  const starkKeyPair = ec.genKeyPair();
33
59
  const starkKeyPub = ec.getStarkKey(starkKeyPair);
34
60
  ```
35
61
 
36
- ## Deploy Account Contract
62
+ You can also get a key pair from a private key using:
37
63
 
38
- Deploy the Account contract and wait for it to be verified on StarkNet.
64
+ `getKeyPair(pk: BigNumberish)`
39
65
 
40
66
  ```javascript
41
- const compiledAccount = json.parse(
42
- fs.readFileSync("./Account.json").toString("ascii")
43
- );
67
+ const privateKey = '0x-Some-Existing-Private-Key'; // you can use stark.randomAddress();
68
+ const starkKeyPair = ec.getKeyPair(privateKey);
69
+ const starkKeyPub = ec.getStarkKey(starkKeyPair);
44
70
  ```
45
71
 
46
- > **Note**
47
- >
48
- > below example uses [Argent's](https://github.com/argentlabs/argent-contracts-starknet/blob/develop/contracts/account/ArgentAccount.cairo) account contract
72
+ ## Pre-compute address of the Account
49
73
 
50
74
  ```javascript
51
- const accountResponse = await defaultProvider.deployContract({
52
- contract: compiledAccount,
53
- addressSalt: starkKeyPub,
54
- });
75
+ const precalculatedAddress = hash.calculateContractAddressFromHash(
76
+ starkKeyPub, // salt
77
+ OZContractClassHash,
78
+ [starkKeyPub],
79
+ 0
80
+ );
55
81
  ```
56
82
 
57
- > **Note**
58
- >
59
- > below example uses [OpenZeppelin's](https://github.com/OpenZeppelin/cairo-contracts/blob/main/src/openzeppelin/account/presets/Account.cairo) account contract
83
+ ## Funding options for the pre-computed address
60
84
 
61
- ```javascript
62
- const accountResponse = await defaultProvider.deployContract({
63
- contract: compiledAccount,
64
- constructorCalldata: [starkKeyPub],
65
- addressSalt: starkKeyPub,
66
- });
85
+ 1. TESTNET
86
+
87
+ You can do so by using a faucet: https://faucet.goerli.starknet.io/
88
+
89
+ 2. DEVNET
90
+
91
+ Address is the newly `precalculatedAddress`.
92
+
93
+ ```bash
94
+ curl -X POST http://127.0.0.1:5050/mint -d '{"address":"0x04a093c37ab61065d001550089b1089922212c60b34e662bb14f2f91faee2979","amount":50000000000000000000,"lite":true}' -H "Content-Type:application/json"
95
+ // {"new_balance":50000000000000000000,"tx_hash":null,"unit":"wei"}
67
96
  ```
68
97
 
69
- ## Use your new account
98
+ 3. Send funds from an already existing account
70
99
 
71
- Wait for the deployment transaction to be accepted and assign the address of the deployed account to the Account object.
100
+ ## OPTIONAL - Declare Account
101
+
102
+ > NOTE: This step will fail if you haven't sent funds to the pre-calculated address.
103
+
104
+ We need to use an already deployed account in order to declare ours. StarkNet will always have at least 1 already declared/deployed account for this purpose.
72
105
 
73
106
  ```javascript
74
- await defaultProvider.waitForTransaction(accountResponse.transaction_hash);
75
- ```
107
+ // In this case we will use the devnet's predeployed OZ account, after you start the devnet with: `starknet-devnet --seed 0`
108
+ const devnetPrivateKey = '0xe3e70682c2094cac629f6fbed82c07cd';
109
+ const devnetAccount0Address = '0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a';
110
+ const devnetKeyPair = ec.getKeyPair(devnetPrivateKey);
76
111
 
77
- Once account contract is deployed [Account](../docs/API/account.md) instance can be created. Use your new account instance to sign transactions, messages or verify signatures!
112
+ const predeployedAccount = new Account(provider, devnetAccount0Address, devnetKeyPair);
78
113
 
79
- ```js
80
- const account = new Account(
81
- defaultProvider,
82
- accountResponse.contract_address,
83
- starkKeyPair
84
- );
114
+ const declareTx = await predeployedAccount.declare({
115
+ classHash: OZContractClassHash,
116
+ contract: compiledOZAccount
117
+ });
118
+
119
+ await provider.waitForTransaction(declareTx.transaction_hash);
85
120
  ```
86
121
 
87
- ## Fund your new account!
122
+ ## Deploy Account Contract
123
+
124
+ Deploy the Account contract and wait for it to be verified on StarkNet.
125
+
126
+ > NOTE: This step will fail if you haven't sent funds to the pre-calculated address.
88
127
 
89
- Make sure your Account has enough funds to execute invocations. Use this [faucet](https://faucet.goerli.starknet.io/) for funding on testnet.
128
+ ```javascript
129
+ const account = new Account(provider, precalculatedAddress, starkKeyPair);
130
+
131
+ // This is OpenZeppelin account contract deployment
132
+ const accountResponse = await account.deployAccount({
133
+ classHash: OZContractClassHash,
134
+ constructorCalldata: [starkKeyPub],
135
+ contractAddress: precalculatedAddress,
136
+ addressSalt: starkKeyPub
137
+ });
138
+
139
+ await provider.waitForTransaction(accountResponse.transaction_hash);
140
+ ```
@@ -4,104 +4,160 @@ sidebar_position: 3
4
4
 
5
5
  # Deploy an ERC20 Contract
6
6
 
7
- Deploy the contract and wait for deployment transaction to be accepted on StarkNet
7
+ Deploying a contract relies on having an account already set up with enough ETH to pay fees for both:
8
+
9
+ 1. The class declaration
10
+ 2. The transaction interacting with the UDC (universal deployer contract)
11
+
12
+ > You must first declare your contract class and only then deploy a new instance of it!
13
+
14
+ High level explanations from StarkWare can be found in this Notion [page](https://starkware.notion.site/Deploy-a-contract-and-an-account-on-StarkNet-ed2fd13301d2414e8223bb72bb90e386).
15
+
16
+ ERC20 implementations:
17
+
18
+ 1. Argent ERC20 contract can be found [here](https://github.com/argentlabs/argent-contracts-starknet/blob/develop/contracts/lib/ERC20.cairo).
19
+ 2. OpenZeppelin ERC20 can be found [here](https://github.com/OpenZeppelin/cairo-contracts/tree/main/src/openzeppelin/token/erc20).
20
+
21
+ ## Setup
8
22
 
9
23
  ```javascript
10
24
  const compiledErc20 = json.parse(
11
25
  fs.readFileSync("./ERC20.json").toString("ascii")
12
26
  );
13
- const erc20Response = await defaultProvider.deployContract({
27
+ ```
28
+
29
+ ```javascript
30
+ // devnet private key from Account #0 if generated with --seed 0
31
+ const starkKeyPair = ec.getKeyPair("0xe3e70682c2094cac629f6fbed82c07cd");
32
+ const accountAddress = "0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a";
33
+
34
+ const recieverAddress = '0x69b49c2cc8b16e80e86bfc5b0614a59aa8c9b601569c7b80dde04d3f3151b79';
35
+
36
+ // Starknet.js currently doesn't have the functionality to calculate the class hash
37
+ const erc20ClassHash = '0x03f794a28472089a1a99b7969fc51cd5fbe22dd09e3f38d2bd6fa109cb3f4ecf';
38
+
39
+ const account = new Account(
40
+ provider,
41
+ accountAddress,
42
+ starkKeyPair
43
+ );
44
+ ```
45
+
46
+ ## Declare contract
47
+
48
+ ```javascript
49
+ const erc20DeclareResponse = await account.declare({
50
+ classHash: erc20ClassHash,
14
51
  contract: compiledErc20,
15
- constructorCalldata: [encodeShortString('TokenName'), encodeShortString('TokenSymbol'), recipient], // Here the `recipient` receives the initial 1000 tokens
16
52
  });
17
53
 
18
- console.log("Waiting for Tx to be Accepted on Starknet - ERC20 Deployment...");
19
- await defaultProvider.waitForTransaction(erc20Response.transaction_hash);
54
+ await provider.waitForTransaction(erc20DeclareResponse.transaction_hash);
20
55
  ```
21
56
 
22
- > **Note**
23
- >
24
- > The ERC20 contract can be found [here](https://github.com/argentlabs/argent-contracts-starknet/blob/develop/contracts/lib/ERC20.cairo)
25
-
26
- ## Get the erc20 contract address and create the contact object
57
+ ## Deploy contract
27
58
 
28
59
  ```javascript
29
- const erc20Address = erc20Response.contract_address;
30
- const erc20 = new Contract(compiledErc20.abi, erc20Address, defaultProvider);
60
+ const salt = '900080545022'; // use some random salt
61
+
62
+ const erc20Response = await account.deploy({
63
+ classHash: erc20ClassHash,
64
+ constructorCalldata: stark.compileCalldata({
65
+ name: shortString.encodeShortString('TestToken'),
66
+ symbol: shortString.encodeShortString('ERC20'),
67
+ decimals: 18,
68
+ initial_supply: ['1000'],
69
+ recipient: account.address,
70
+ }),
71
+ salt,
72
+ });
73
+
74
+ await provider.waitForTransaction(erc20Response.transaction_hash);
75
+
76
+ const txReceipt = await provider.getTransactionReceipt(erc20Response.transaction_hash);
31
77
  ```
32
78
 
33
- ## Mint tokens to an account address
79
+ ## Interact with contracts
34
80
 
35
- Make sure you created the `Account` instance following the [Creating an Account](./account.md) guide.
81
+ We have 2 options to interact with contracts.
36
82
 
37
- Also make sure you added funds to your account!
83
+ ### Option 1 - call the contract object
38
84
 
39
85
  ```javascript
86
+ const erc20 = new Contract(compiledErc20.abi, erc20Address, provider);
87
+
40
88
  erc20.connect(account);
41
89
 
42
- const { transaction_hash: mintTxHash } = await erc20.mint(
43
- account.address,
44
- [ "1000", "0"]
90
+ const { transaction_hash: mintTxHash } = await erc20.transfer(
91
+ recieverAddress,
92
+ ['0', '10'], // send 10 tokens as Uint256
93
+ );
94
+
95
+ await provider.waitForTransaction(mintTxHash);
96
+ ```
97
+
98
+ ### Option 2 - call contract from Account
99
+
100
+ ```javascript
101
+ const executeHash = await account.execute(
45
102
  {
46
- maxFee: "1"
103
+ contractAddress: erc20Address,
104
+ entrypoint: 'transfer',
105
+ calldata: stark.compileCalldata({
106
+ recipient: recieverAddress,
107
+ amount: ['10']
108
+ })
47
109
  }
48
110
  );
49
111
 
50
- console.log(`Waiting for Tx to be Accepted on Starknet - Minting...`);
51
- await defaultProvider.waitForTransaction(mintTxHash);
112
+ await provider.waitForTransaction(executeHash.transaction_hash);
52
113
  ```
53
114
 
54
- > **Note**
55
- >
56
- > Transaction can be rejected if `maxFee` is lower than actual.
57
- >
58
- > _Error: REJECTED: FEE_TRANSFER_FAILURE_
59
- >
60
- > _Actual fee exceeded max fee._
61
- >
62
- > If this occurs, set `maxFee` to a higher value, for example: 999999995330000
63
-
64
- ## Check balance after mint
115
+ ## Check the balance
65
116
 
66
117
  ```javascript
67
- console.log(`Calling StarkNet for account balance...`);
68
118
  const balanceBeforeTransfer = await erc20.balanceOf(account.address);
69
119
 
70
120
  console.log(
71
121
  `account Address ${account.address} has a balance of:`,
72
- number.toBN(balanceBeforeTransfer.balance.low, 16).toString()
122
+ number.toBN(balanceBeforeTransfer[0].high).toString()
73
123
  );
74
124
  ```
75
125
 
76
- ## Transfer tokens
126
+ ## Convenience Methods
77
127
 
78
- ```javascript
79
- // Execute tx transfer of 10 tokens
80
- console.log(`Invoke Tx - Transfer 10 tokens back to erc20 contract...`);
81
- const { transaction_hash: transferTxHash } = await account.execute(
82
- {
83
- contractAddress: erc20Address,
84
- entrypoint: "transfer",
85
- calldata: [erc20Address, "10", "0"],
86
- },
87
- undefined,
88
- { maxFee: "1" }
89
- );
128
+ ### deployContract convenience method
129
+
130
+ High level wrapper for deploy. Doesn't require `waitForTransaction`. Response similar to deprecated `provider.deployContract`.
131
+
132
+ Convenient also to get the address of the deployed contract in the same response - easier than using the `deploy` already mentioned in the guide.
90
133
 
91
- // Wait for the invoke transaction to be accepted on StarkNet
92
- console.log(`Waiting for Tx to be Accepted on Starknet - Transfer...`);
93
- await defaultProvider.waitForTransaction(transferTxHash);
134
+ ```typescript
135
+ const deployResponse = await account.deployContract({
136
+ classHash: erc20ClassHash,
137
+ constructorCalldata: [
138
+ encodeShortString('Token'),
139
+ encodeShortString('ERC20'),
140
+ account.address,
141
+ ],
142
+ });
94
143
  ```
95
144
 
96
- ## Check balance after transfer
145
+ ### declareDeploy convenience method
97
146
 
98
- ```javascript
99
- // Check balance after transfer - should be 1990 (1000 initial supply + 1000 mint - 10 transfer)
100
- console.log(`Calling StarkNet for account balance...`);
101
- const balanceAfterTransfer = await erc20.balanceOf(account.address);
147
+ High level wrapper for declare & deploy. Doesn't require `waitForTransaction`. Functionality similar to deprecated `provider.deployContract`.
102
148
 
103
- console.log(
104
- `account Address ${account.address} has a balance of:`,
105
- number.toBN(balanceAfterTransfer.balance.low, 16).toString()
106
- );
149
+ Declare and Deploy contract using single function:
150
+
151
+ ```typescript
152
+ const declareDeploy = await account.declareDeploy({
153
+ contract: compiledErc20,
154
+ classHash: '0x54328a1075b8820eb43caf0caa233923148c983742402dcfc38541dd843d01a',
155
+ constructorCalldata: [
156
+ encodeShortString('Token'),
157
+ encodeShortString('ERC20'),
158
+ account.address,
159
+ ],
160
+ });
161
+ const declareTransactionHash = declareDeploy.declare.transaction_hash
162
+ const erc20Address = declareDeploy.deploy.contract_address;
107
163
  ```
@@ -5,9 +5,12 @@ sidebar_position: 1
5
5
  # Getting Started
6
6
 
7
7
  ```bash
8
+
9
+ # use the main branch
10
+
8
11
  npm install starknet
9
12
 
10
- # to use latest features
13
+ # to use latest features (merges in develop branch)
11
14
 
12
15
  npm install starknet@next
13
16
  ```
@@ -16,8 +19,12 @@ npm install starknet@next
16
19
 
17
20
  Please check the StarkNet documentation <ins>[here](https://www.cairo-lang.org/docs/hello_starknet/intro.html)</ins> to compile starknet contracts.
18
21
 
19
- Additional helpful resources can also be found at [OpenZeppelin](https://docs.openzeppelin.com/contracts-cairo/0.3.1/) documentation site.
22
+ Additional helpful resources can also be found at <ins>[OpenZeppelin](https://docs.openzeppelin.com/contracts-cairo/0.5.0/)</ins> documentation site.
23
+
24
+ Get the class hash of a contract: [starkli](https://github.com/xJonathanLEI/starkli).
25
+
26
+ ## Full example with account & erc20 deployments
20
27
 
21
- ## Full example with account & erc20
28
+ Please take a look at our workshop using OpenZeppelin contracts <ins>[here](https://github.com/0xs34n/starknet.js-workshop)</ins>.
22
29
 
23
- Please take a look at our workshop <ins>[here](https://github.com/0xs34n/starknet.js-workshop)</ins>.
30
+ Example with Argent contract <ins>[here](https://github.com/0xs34n/starknet.js-account)</ins>.