starknet-io / starknet.js Goto Github PK
View Code? Open in Web Editor NEWJavaScript library for StarkNet
Home Page: https://www.starknetjs.com
License: MIT License
JavaScript library for StarkNet
Home Page: https://www.starknetjs.com
License: MIT License
I noticed that when using this library with a project created with create-react-app
users get a TypeError
generated in typedData
. This doesn't seems to be related to #37.
I created a repo to reproduce this issue here.
I attached the log file generated by Chrome.
localhost-1644609483259.log
data: {
code: 'StarknetErrorCode.SECURITY_ERROR',
message: 'Invalid value for field prime:
3618502788666131106986593281521497120414687020801267626233049500247285301248. Expected:
3.618502788666131e+75.
3618502788666131213697322783095070105623107215331596699973092056135872020481.'
}
Getting the following error when deploying the AMM compiled code here
However, it works when you use the starknet deploy
command
My suggestion:
function waitForTxV2(
txHash: utils.number.BigNumberish,
retryInterval: number = 1000,
func: Function
) {
console.log("=== WAIT FOR TX V2 STARTED ===");
const interval = setInterval(async () => {
const transactionResponse = await getTransactionStatus(txHash);
console.log("=== TRANSACTION STATUS ===", transactionResponse.tx_status);
func(transactionResponse.tx_status);
if (
transactionResponse.tx_status === "PENDING" || // Success State
transactionResponse.tx_status === "ACCEPTED_ONCHAIN" || // Success State
transactionResponse.tx_status === "REJECTED" // Failure State
) {
clearInterval(interval);
}
}, retryInterval);
// clear interval after 90 seconds
setTimeout(() => {
console.log("=== 90 seconds are up... clearing interval ===");
clearInterval(interval);
}, 90000);
}
Signer should get an additional method verifyMessage(typedData: TypedData, signature: Signature): Promise<boolean>
, which allows the signer to check if the given signature signs the given message using the signers pub key.
There should also be a verifyMessageHash(typedDataHash: BigNumberish, signature: Signature): Promise<boolean>
, which allows the signer to check if the given signature is valid for the account by calling is_valid_signature
on the account contract.
Something like this:
export function invokeFunction(contractAddress, signature, callData, entrypointSelector) {
return addTransaction({
type: 'INVOKE_FUNCTION',
contract_address: contractAddress,
signature,
calldata: callData,
entry_point_selector: entrypointSelector,
});
}
Maybe let's improve documentation around it?
I made an example using this library with react, everything is working fine in development, but in production it looks like starknet.js is throwing a type error. You can open this page to see the error more in detail.
To reproduce locally:
yarn run build
yarn run serve
Hey team,
I was wondering if the following utilities would be a good place for this repo:
/**
* Converts a string into an array of numerical characters in utf-8 encoding
* @param {string} str - The string to convert
* @returns {bigint[]} - The string converted as an array of numerical characters
*/
export function stringToFeltArray(str: string): bigint[] {
const strArr = str.split('');
return strArr.map(char => BigInt(Buffer.from(char)[0].toString(10)));
}
/**
* Converts an array of utf-8 numerical characters into a readable string
* @param {bigint[]} felts - The array of numerical characters
* @returns {string} - The readable string
*/
export function feltArrayToString(felts: bigint[]): string {
return felts.reduce((memo, felt) => memo + Buffer.from(felt.toString(16), 'hex').toString(), '');
}
I found these utilities useful for the scenario:
to convert a string -> [felt]
so that it can be passed as an argument to a function with parameters: arg_len: felt, arg: felt*
:
I can create the PR if that works for everyone!
He basically built the library lol
The API we want to expose with this package has rapidly expanded.
I think it'd be good timing to discuss the exposed methods and objects, to prevent future surprises.
I really like the simplicity introduced by @seanjameshan initially, by exposing the api endpoints as is. But with introducing more complex types like contracts and accounts we need to find a middle ground.
I'd like to introduce a simple yet extensible api for developers to use.
Simple and extensible api:
Lets assume defaults, but also expose the building blocks used onto of those defaults.
ie: Starknet Goerli Alphanet is the only one accessible right now. This won't stay this way, with main net approaching quick. Lets always expose a simple (opinionated) export to get the developer started right away, aswell as a class contructor where you can pass your own arguments.
// Beginner
import { api } from "starknet.js"
// assuming goerli alpha and subject to change
const { Starknet, GpsStatementVerifier } = await api.getContractAddresses()
// Advanced
import { Api } from "starknet.js"
const localApi = new Api({ endpoint: "http://localhost:3002" })
const { Starknet, GpsStatementVerifier } = await localApi.getContractAddresses()
Classes:
On top of that I think it makes sense to introduce some Classes, to leave the choice of if a develop wants to use OOP or a more functional style. ie:
// functional
import { wallet } from "starknet.js"
const { getKeyPair, sign, getStarkKey } = wallet
const kp = getKeyPair("Private Key")
const address = getStarkKey(kp)
const sig = sign(kp, "hello")
// object oriented
import { Wallet } from "starknet.js"
const wallet = Wallet("Private Key")
const address = wallet.getStarkKey()
const sig = wallet.sign(kp, "hello")
In the 0.7.0 version, StarkNet began to support events. So maybe it is possible to add an events subscription, as in the Web3.js.
Documentation:
One of our dependencies https://github.com/sidorares/json-bigint has seen it's best days.
It uses bignumber.js as a dependency, while this library uses bn.js. It also supports native BigInt which breaks support for older browsers and browserslists (see #37 ).
Lets reimplement this package in TS.
As a starting point we can use the test suites provided at the original repo and write an implementation against it.
We can ether make this repo a monorepo or start a new repo.
It seems unit tests are running against the defaultProvider
which is goerli, making the tests really slow.
An example of a localhost test runner can be found here: https://github.com/argentlabs/argent-x/blob/develop/.github/workflows/test.yml#L14
getSelectorFromName()
is used very frequently with dapps. Every time I make a smart contract call I would have to import like the following:
const {
starknet: { getSelectorFromName },
} = utils;
Would prefer this import instead:
import { getSelectorFromName, addTransaction } from "starknet";
I am not using Provider / Signer at the moment so this could possibly be outdated
We are already converting Args to Array using Object.values(args)
. Why not to just pass an Array in the form of positional arguements to compileCalldata? ethers.js
do this as well.
__tests__
main
branch failed. 🚨I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this 💪.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the main
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here are some links that can help you:
If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.
1.5.3
on branch main
cannot be published as it is out of range.Based on the releases published on other branches, only versions within the range >=1.5.2 <1.5.3
can be published from branch main
.
The following commits are responsible for the invalid release:
Those commits should be moved to a valid branch with git merge or git cherry-pick and removed from branch main
with git revert or git reset.
A valid branch could be develop
.
See the workflow configuration documentation for more details.
Good luck with your project ✨
Your semantic-release bot 📦🚀
As contract addresses are now deterministic with StarkNet Alpha3 (#29) lets implement a method to calculate the contract address given the deployment transaction details
Reference in python:
https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/starknet/services/api/gateway/contract_address.py
Hey Sean!
can we maybe change the default branch to develop
?
It'd improve DX as PRs would be created against develop and also improve release automation, as issues do not get closed if a PR fixing it isn't targeting the default branch.
As the documentation lives on a webpage by now, it would still be valid for the main rpm package :-)
I believe the url is alpha3.starknet.io
The release commit will also generate docs for develop
and main
branches
__tests__
invokeTx
Calling contract’s function transforms python types to Cairo types based on ABI:
int -> felt
tuple -> tuple
iterable -> array
dict -> struct
Function result is transformed from Cairo types to Python types.
Should we replace axios by some isomorphic fetch implementation to have less dependencies in case the used environment already has fetch available? :) It would not introduce any extra complexity as we can't use most of axis advantages anyways when handling biting json data.
Would love to hear your thoughts @seanjameshan
I'd suggest https://github.com/lquixada/cross-fetch
To be implemented on Provider
Currently,
export type Args = { [inputName: string]: string | string[] | { type: 'struct'; [k: string]: BigNumberish }; };
The type of Args
does not include a type Uint256 which is a normal JS object with low
and high
properties. How should it be parsed on frontend?
For example,
Example ABI:
{ "inputs": [ { "name": "account", "type": "felt" } ], "name": "balanceOf", "outputs": [ { "name": "balance", "type": "Uint256" } ], "stateMutability": "view", "type": "function" }
The output of balanceOf
call will be of type Args
const result = contract.call(balanceOf, { account: address }) // returns result = { balance: Object }
Here, the type of balance
is neither string
, string[]
or struct
.
Type string | string[] | { type: 'struct'; [k: string]: BigNumberish
is also not compatible with arguement of uint256ToBN()
.
Currently, I am passing result as any
in uint256ToBN
which is not a good way to do this.
Research if blockId
in any method can be optional (aka null
). At least it works for this api:
https://alpha2.starknet.io/feeder_gateway/get_block?blockId=null
Maybe also add a helper method to fetch exactly that endpoint and return the block number, as that's a common use case.
The method could be called getBlockNumber
.
ref:
https://discord.com/channels/793094838509764618/793094838987128844/900767794285649950
https://discord.com/channels/793094838509764618/793094838987128844/901123694523482152
https://discord.com/channels/793094838509764618/793094838987128844/901260335296704582
could potentially use https://www.npmjs.com/package/json-bigint to avoid this problem. I've checked that it can solve at least part of the difference in the program compression pipelines (when employed as in https://gist.github.com/RoboTeddy/41bd89ea8a4ac3df53c6d883de5a0501)
Currently, we can't display to users any details about failure transactions. We only have a status code. But get_transaction_status
also sends us the tx_failure_reason
, and I think we should be able to read this reason
after #21 gets merged
Using the function getBlock() with a custom block number it doesn't return the correct block example:
https://alpha-mainnet.starknet.io/feeder_gateway/get_block?blockId=123
@janek26 Feel free to add more context to this use case.
Create a nice interface for developers to sent invokeFunction transactions through the addTransaction
method using the ABI
throw an error in starknet.js if input object has additional keys that cant be used as input arguments
https://github.com/seanjameshan/starknet.js/blob/d9ec6d3ea3cc0dbf3538fb2fe7b5e1d8a8831490/src/contract.ts#L76
As a dev it's annoying if you pass an object which looks right but don't get an error.
example: argentlabs/argent-x#382
maybe somebody can pick tis up faster than I can.
End-to-end and comprehensive guides on how to use StarkNet.js
version 2.5
More context: https://discordapp.com/channels/793094838509764618/927918707613786162/930855057568727141
Sending Uint256
end up with a REJECT transaction
Same values send from starknet cli wor
k
Error
/home/filip/.local/lib/python3.8/site-packages/starkware/starknet/common/storage.cairo:22:5: Error at pc=0:91:
if is_small != 0:
^^
Got an exception while executing a hint.
Cairo traceback (most recent call last):
/path/to/my-project/contracts/utils/token/ERC20.cairo:19:6
func constructor{
^*********^
/path/to/my-project/contracts/utils/token/ERC20.cairo:29:5
ERC20_initializer(name, symbol, initial_supply, recipient)
^********************************************************^
/path/to/my-project/contracts/utils/token/ERC20_base.cairo:54:5
ERC20_mint(recipient, initial_supply)
^***********************************^
/path/to/my-project/contracts/utils/token/ERC20_base.cairo:135:30
let (balance: Uint256) = ERC20_balances.read(account=recipient)
^************************************^
autogen/starknet/storage_var/ERC20_balances/impl.cairo:16:30
let (storage_addr) = addr(account)
^***********^
autogen/starknet/storage_var/ERC20_balances/impl.cairo:10:21
let (res) = normalize_address(addr=res)
^*************************^
Traceback (most recent call last):
File "<hint5>", line 5, in <module>
AssertionError: normalize_address() cannot be used with the current constants.
I was receiving the error AssertionError: normalize_address() cannot be used with the current constants
when calling a contract I deployed with provider.deployContract
. After investigating the issue with Tom (starknet) on discord he has suggested that it is possibly something to do with the way starknet JS is handling ints from the compile_contract.json
file that is passed in as the first argument to deployContract
This is the code I am using to deploy my contract:
const calldata = compileCalldata({
name: nameFelt,
symbol: symbolFelt,
owner: account,
});
const resp = await provider.deployContract(compiledERC721, calldata);
This is the JSON file:
And here is a script that shows the error when calling a contract deployed with the starknet CLI that works and then that same contract deployed with starknet.js that doesn't work:
Appreciate the time and help
Contract::ParseResponse does not support array-return types (X_len:felt, X: felt*). Instead the current method returns two variables with the length & the first value.
I am not clear whether Cairo intends to support struct return values, which also would entail changes to this function.
Instance methods like invokeFunction should do more preprocessing and not expect results from helper functions like getSelectorFromName or compileCalldata.
This will allow other actors in the ecosystem to implement their own Provider or Signer, with the ability to show human readable data to the user. This is very important for wallets, but also Hardware wallets like Ledger, so we don't just approve hashes and hex values like we do in Ethereum today.
entry_point_selector
It should always be the human readable string, like "mint" or "transfer". It should not be a pre-computed address like the result of getSelectorFromName or any other hex value.
calldata
This one is a little bit more complicated. Basically there are 2 difference appearances of calldata. In Providers and Signers the calldata normally isn't aware of any ABI or context. In these cases, like addTransaction there should be a 2nd parameter which accepts an ABI. This way signers like Argent X, Ledger or whatever, can show relevant information to the user approving. This parameter should be optional, and wallets can handle it differently if it's not provided (deny signing, display warning etc).
signature
Signatures should not assume that there's just one signing party. Signature is always a flat array of BigNumberish with variable length n.
As Starkware released starknet alpha v4 today, lets make sure to support it asap.
I can begin to work at this issue as early as tomorrow morning (CET).
The global wipe is also a great opportunity to introduce the newly agreed signing (hashing) algo to the wallet. ref: https://github.com/OpenZeppelin/cairo-contracts/pull/49/files
The StarkNet in the latest update has split PENDING
status into PENDING
and ACCEPTED_ON_L2
. So we need to add ACCEPTED_ON_L2
in the "waitForTx" method
Also transaction hashes are now deterministic with StarkNet Alpha3 (#29) lets implement a method to calculate the transaction hash given the transaction details
Reference in python:
https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/starknet/services/api/gateway/transaction_hash.py
(not as important, and maybe depending on #32
Originally posted by janek26 January 12, 2022
Hey all,
today I'll propose new interfaces for Provider
, Signer
and especially Contract
.
Provider
and Signer
A Provider should stay similar to an ethers.js Provider, allowing for interactions with the blockchain without signing. Traditionally these are reading states from the blockchain, but due to how StarkNet is build you can do a little more with it in starknet.js, like sending contract deployment transactions etc.
A Signer extends a Provider and inherits/implements all of its methods. It also introduces some methods which are just possible with a Signer, eg creating/verifying signatures. It's primarily interacting with an account contract on starknet.
Signer should get an additional method verifyMessage(typedData: TypedData, signature: Signature): Promise<boolean>
, which allows the signer to check if the given signature signs the given message using the signers pub key.
There should also be a verifyMessageHash(typedDataHash: BigNumberish, signature: Signature): Promise<boolean>
, which allows the signer to check if the given signature is valid for the account by calling is_valid_signature
on the account contract.
Instance methods like invokeFunction
should do more preprocessing and not expect results from helper functions like getSelectorFromName
or compileCalldata
.
This will allow other actors in the ecosystem to implement their own Provider
or Signer
, with the ability to show human readable data to the user. This is very important for wallets, but also Hardware wallets like Ledger, so we don't just approve hashes and hex values like we do in Ethereum today.
entry_point_selector
It should always be the human readable string, like "mint
" or "transfer
". It should not be a pre-computed address like the result of getSelectorFromName
or any other hex value.
calldata
This one is a little bit more complicated. Basically there are 2 difference appearances of calldata
. In Providers and Signers the calldata normally isn't aware of any ABI or context. In these cases, like addTransaction
there should be a 2nd parameter which accepts an ABI. This way signers like Argent X, Ledger or whatever, can show relevant information to the user approving. This parameter should be optional, and wallets can handle it differently if it's not provided (deny signing, display warning etc).
signature
Signatures should not assume that there's just one signing party. Signature is always a flat array of BigNumberish
with variable length n
.
Contract
Contracts can do data transforming in JS based on an ABI. They can also call and invoke to starknet through a provided Signer.
We should split between Contract and ContractFactory (which is also able to deploy contracts) like they do with ethers.js
Contracts should be able to transform most common Cairo values, like Uint256
, to JS objects like BigNumber. It could also allow the user to pass there own transformers, similar to how JSON.parse
does it.
Implement a function which can validate and parse Starknet addresses
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.