Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix parity between local blockchain and network APIs #1422

Merged
merged 63 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
9fe48d7
refactor(mina.ts, mina-instance.ts): rename TransactionId interface t…
MartinMinkov Feb 7, 2024
1655306
refactor(fetch.ts): add generic type support to FetchResponse and rel…
MartinMinkov Feb 8, 2024
168a546
feat(fetch.ts, mina.ts): add missing properties to PendingTransaction
MartinMinkov Feb 8, 2024
a48ec9a
feat(fetch.ts): add type for `lastBlockQuery`
MartinMinkov Feb 8, 2024
25bd926
feat(fetch.ts): add type for `lastBlockQueryFailure`
MartinMinkov Feb 8, 2024
d105637
feat(fetch.ts): add response type for 'transactionStatus'
MartinMinkov Feb 8, 2024
82c4913
refactor(fetch.ts): remove temporary fix for fetching event/action da…
MartinMinkov Feb 8, 2024
e77dd4f
feat(fetch.ts): add type for 'getActions'
MartinMinkov Feb 8, 2024
fa4208c
refactor(graphql.ts): add a graphql module under mina dir
MartinMinkov Feb 8, 2024
c861ff7
feat(mina.ts): add IncludedTransaction type to handle transactions th…
MartinMinkov Feb 8, 2024
4a9af9d
feat(mina.ts): modify wait function to return IncludedTransaction
MartinMinkov Feb 8, 2024
89d2bcc
refactor(mina.ts): simplify transaction status polling logic
MartinMinkov Feb 8, 2024
50a7e5c
fix(run_live.ts): change types from Mina.TransactionId to Mina.Pendin…
MartinMinkov Feb 8, 2024
08ab94f
feat(mina.ts): add IncludedTransaction to exports to allow access to …
MartinMinkov Feb 8, 2024
9f6a8b4
refactor(mina.ts): simplify IncludedTransaction type definition using…
MartinMinkov Feb 8, 2024
cd3808e
feat(mina.ts): add sendOrThrowIfError method to Transaction type
MartinMinkov Feb 12, 2024
2329353
feat(mina.ts): add RejectedTransaction type and waitOrThrowIfError
MartinMinkov Feb 12, 2024
6e49d78
feat(mina.ts): add RejectedTransaction to exports
MartinMinkov Feb 12, 2024
baa33d3
fix(mina.ts): throw error when transaction is rejected to handle tran…
MartinMinkov Feb 12, 2024
a9de01e
Merge branch 'main' into feat/transaction-flow-txn-type
MartinMinkov Feb 12, 2024
63999a5
Merge branch 'main' into feat/transaction-flow-txn-type
MartinMinkov Feb 13, 2024
b06cfcf
refactor(graphql.ts): rename import from 'account_update.js' to 'acco…
MartinMinkov Feb 13, 2024
8cf9baf
refactor(fetch.ts, account.ts, graphql.ts): move FetchedAccount type …
MartinMinkov Feb 13, 2024
4060d89
feat(fetch.ts, graphql.ts): add GenesisConstants type to handle genes…
MartinMinkov Feb 14, 2024
f3906d2
feat(fetch.ts, graphql.ts): add fetchCurrentSlot function and Current…
MartinMinkov Feb 14, 2024
bc35163
feat(tests): add transaction-flow test suite for zkApp
MartinMinkov Feb 15, 2024
d0e3043
feat(run-ci-live-tests.sh): add transaction-flow test to CI live test…
MartinMinkov Feb 15, 2024
cff8b4d
feat(mina.ts): use 'hashZkAppCommand' to hash transaction
MartinMinkov Feb 16, 2024
06ecf3e
feat(submodule): update mina to b9ed54 and o1js-bindings to 4c847f
MartinMinkov Feb 16, 2024
ec34710
refactor(fetch.ts, graphql.ts): move removeJsonQuotes function from f…
MartinMinkov Feb 16, 2024
166a501
refactor(transaction-flow.ts): replace let with const for immutability
MartinMinkov Feb 16, 2024
0a3f4a0
refactor(fetch.unit-test.ts): replace Fetch.removeJsonQuotes with rem…
MartinMinkov Feb 16, 2024
f1ec38f
refactor(graphql.ts): modify import statements
MartinMinkov Feb 16, 2024
6b4c68c
refactor(fetch.ts): rename 'txnId' to 'transactionHash'
MartinMinkov Feb 17, 2024
1ede894
refactor(mina.ts): improve error handling and transaction status chec…
MartinMinkov Feb 17, 2024
76574c2
refactor(transaction-flow.ts): modify tests to test throwing methods
MartinMinkov Feb 17, 2024
9b78cc0
refactor(fetch.ts): simplify failureReason mapping in checkZkappTrans…
MartinMinkov Feb 19, 2024
23b32ec
refactor(errors.ts): improve error handling for fee payer and account…
MartinMinkov Feb 19, 2024
aac4e34
refactor(mina.ts): simplify error handling in sendOrThrowIfError, Loc…
MartinMinkov Feb 19, 2024
111bae1
refactor(precondition.test.ts, token.test.ts): replace send() with se…
MartinMinkov Feb 19, 2024
9c214e5
refactor(transaction-flow.ts): remove outdated comments about current…
MartinMinkov Feb 19, 2024
023d31d
feat(mina.ts): add detailed comments for PendingTransaction, Included…
MartinMinkov Feb 19, 2024
671c35e
docs(mina.ts): update comments for better clarity and add examples
MartinMinkov Feb 19, 2024
c8d1d14
style(mina.ts): remove unnecessary comment lines
MartinMinkov Feb 19, 2024
78f96f7
Merge branch 'main' into feat/transaction-flow-txn-type
MartinMinkov Feb 19, 2024
9ca996b
refactor: replace 'send' method with 'sendOrThrowIfError' in dex/run.…
MartinMinkov Feb 19, 2024
d2322e0
refactor(run.ts): replace send() with sendOrThrowIfError() for better…
MartinMinkov Feb 19, 2024
88fa9e2
feat(mina.ts): add error handling for JSON parsing in LocalBlockchain…
MartinMinkov Feb 19, 2024
c4aefd4
fix(run.ts): correct function call syntax for sendOrThrowIfError method
MartinMinkov Feb 20, 2024
9747048
refactor(transaction): move transaction implementations to new module
MartinMinkov Feb 20, 2024
62eade2
feat(local-blockchain): seperate local-blockchain into it's own module
MartinMinkov Feb 20, 2024
1aa462b
refactor(mina.ts): move transaction validation functions to separate …
MartinMinkov Feb 21, 2024
cdad58f
refactor(mina.ts, local-blockchain.ts, transaction.ts): change hash m…
MartinMinkov Feb 21, 2024
0fdac18
refactor(errors.ts): simplify error handling logic by removing accoun…
MartinMinkov Feb 21, 2024
f1ffe88
feat(local-blockchain.ts): add error handling for rejected transactions
MartinMinkov Feb 21, 2024
b13b3e8
chore(bindings): update bindings submodule to a7ade
MartinMinkov Feb 21, 2024
463768a
refactor(transaction-flow.ts): replace try-catch block with assert.re…
MartinMinkov Feb 21, 2024
2551979
Merge branch 'main' into feat/transaction-flow-txn-type
MartinMinkov Feb 21, 2024
638f42a
refactor(mina.ts, transaction.ts): move transaction function from min…
MartinMinkov Feb 21, 2024
e12d29e
refactor(run-live.ts): replace hash() method with hash property for b…
MartinMinkov Feb 21, 2024
39645aa
docs(CHANGELOG.md): update changelog with recent fixes and changes
MartinMinkov Feb 21, 2024
5ea85ac
refactor(mina.ts, mina-instance.ts): move function definitions from m…
MartinMinkov Feb 21, 2024
069921c
docs(CHANGELOG.md): move transaction changes to 'Breaking changes' se…
MartinMinkov Feb 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased](https://github.com/o1-labs/o1js/compare/3b5f7c7...HEAD)

### Breaking changes

- Fixed parity between `Mina.LocalBlockchain` and `Mina.Network` to have the same behaviors https://github.com/o1-labs/o1js/pull/1422
- Changed the `TransactionId` type to `Transaction`. Additionally added `PendingTransaction` and `RejectedTransaction` types to better represent the state of a transaction.
- `transaction.send()` no longer throws an error if the transaction was not successful for `Mina.LocalBlockchain` and `Mina.Network`. Instead, it returns a `PendingTransaction` object that contains the error. Use `transaction.sendOrThrowIfError` to throw the error if the transaction was not successful.
- `transaction.wait()` no longer throws an error if the transaction was not successful for `Mina.LocalBlockchain` and `Mina.Network`. Instead, it returns either a `IncludedTransaction` or `RejectedTransaction`. Use `transaction.waitOrThrowIfError` to throw the error if the transaction was not successful.
- `transaction.hash()` is no longer a function, it is now a property that returns the hash of the transaction.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


### Added

- Support for custom network identifiers other than `mainnet` or `testnet` https://github.com/o1-labs/o1js/pull/1444
Expand Down
9 changes: 9 additions & 0 deletions run-ci-live-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ HELLO_WORLD_PROC=$!
DEX_PROC=$!
./run src/examples/fetch-live.ts --bundle | add_prefix "FETCH" &
FETCH_PROC=$!
./run src/tests/transaction-flow.ts --bundle | add_prefix "TRANSACTION_FLOW" &
TRANSACTION_FLOW_PROC=$!

# Wait for each process and capture their exit statuses
FAILURE=0
Expand All @@ -43,6 +45,13 @@ if [ $? -ne 0 ]; then
echo ""
FAILURE=1
fi
wait $TRANSACTION_FLOW_PROC
if [ $? -ne 0 ]; then
echo ""
echo "TRANSACTION_FLOW test failed."
echo ""
FAILURE=1
fi

# Exit with failure if any process failed
if [ $FAILURE -ne 0 ]; then
Expand Down
10 changes: 6 additions & 4 deletions src/examples/zkapps/dex/run-live.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const network = Mina.Network({
});
Mina.setActiveInstance(network);

let tx, pendingTx: Mina.TransactionId, balances, oldBalances;
let tx, pendingTx: Mina.PendingTransaction, balances, oldBalances;

// compile contracts & wait for fee payer to be funded
const senderKey = useCustomLocalNetwork
Expand Down Expand Up @@ -285,13 +285,15 @@ async function ensureFundedAccount(privateKeyBase58: string) {
return { senderKey, sender };
}

function logPendingTransaction(pendingTx: Mina.TransactionId) {
function logPendingTransaction(pendingTx: Mina.PendingTransaction) {
if (!pendingTx.isSuccess) throw Error('transaction failed');
console.log(
'tx sent: ' +
(useCustomLocalNetwork
? `file://${os.homedir()}/.cache/zkapp-cli/lightnet/explorer/<version>/index.html?target=transaction&hash=${pendingTx.hash()}`
: `https://minascan.io/berkeley/tx/${pendingTx.hash()}?type=zk-tx`)
? `file://${os.homedir()}/.cache/zkapp-cli/lightnet/explorer/<version>/index.html?target=transaction&hash=${
pendingTx.hash
}`
: `https://minascan.io/berkeley/tx/${pendingTx.hash}?type=zk-tx`)
);
}

Expand Down
24 changes: 15 additions & 9 deletions src/examples/zkapps/dex/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@ async function main({ withVesting }: { withVesting: boolean }) {
(USER_DX * oldBalances.total.lqXY) / oldBalances.dex.X
);
} else {
await expect(tx.send()).rejects.toThrow(/Update_not_permitted_timing/);
await expect(tx.sendOrThrowIfError()).rejects.toThrow(
/Update_not_permitted_timing/
);
}

/**
Expand All @@ -252,14 +254,14 @@ async function main({ withVesting }: { withVesting: boolean }) {
});
await tx.prove();
tx.sign([keys.user2]);
await expect(tx.send()).rejects.toThrow(/Overflow/);
await expect(tx.sendOrThrowIfError()).rejects.toThrow(/Overflow/);
console.log('supplying with insufficient tokens (should fail)');
tx = await Mina.transaction(addresses.user, () => {
dex.supplyLiquidityBase(UInt64.from(1e9), UInt64.from(1e9));
});
await tx.prove();
tx.sign([keys.user]);
await expect(tx.send()).rejects.toThrow(/Overflow/);
await expect(tx.sendOrThrowIfError()).rejects.toThrow(/Overflow/);

/**
* - Resulting operation will overflow the SC’s receiving token by type or by any other applicable limits;
Expand All @@ -278,7 +280,7 @@ async function main({ withVesting }: { withVesting: boolean }) {
);
});
await tx.prove();
await tx.sign([feePayerKey, keys.tokenY]).send();
await tx.sign([feePayerKey, keys.tokenY]).sendOrThrowIfError();
console.log('supply overflowing liquidity');
await expect(async () => {
tx = await Mina.transaction(addresses.tokenX, () => {
Expand All @@ -289,7 +291,7 @@ async function main({ withVesting }: { withVesting: boolean }) {
});
await tx.prove();
tx.sign([keys.tokenX]);
await tx.send();
await tx.sendOrThrowIfError();
}).rejects.toThrow();

/**
Expand All @@ -316,7 +318,7 @@ async function main({ withVesting }: { withVesting: boolean }) {
dex.supplyLiquidity(UInt64.from(10));
});
await tx.prove();
await expect(tx.sign([keys.tokenX]).send()).rejects.toThrow(
await expect(tx.sign([keys.tokenX]).sendOrThrowIfError()).rejects.toThrow(
/Update_not_permitted_balance/
);

Expand All @@ -343,7 +345,9 @@ async function main({ withVesting }: { withVesting: boolean }) {
});
await tx.prove();
tx.sign([keys.user]);
await expect(tx.send()).rejects.toThrow(/Source_minimum_balance_violation/);
await expect(tx.sendOrThrowIfError()).rejects.toThrow(
/Source_minimum_balance_violation/
);

// another slot => now it should work
Local.incrementGlobalSlot(1);
Expand Down Expand Up @@ -452,7 +456,7 @@ async function main({ withVesting }: { withVesting: boolean }) {
});
await tx.prove();
tx.sign([keys.user, keys.user2]);
await expect(tx.send()).rejects.toThrow(
await expect(tx.sendOrThrowIfError()).rejects.toThrow(
/Account_balance_precondition_unsatisfied/
);

Expand Down Expand Up @@ -487,7 +491,9 @@ async function main({ withVesting }: { withVesting: boolean }) {
dex.redeemLiquidity(UInt64.from(1n));
});
await tx.prove();
await expect(tx.sign([keys.user2]).send()).rejects.toThrow(/Overflow/);
await expect(tx.sign([keys.user2]).sendOrThrowIfError()).rejects.toThrow(
/Overflow/
);
[oldBalances, balances] = [balances, getTokenBalances()];

/**
Expand Down
18 changes: 9 additions & 9 deletions src/examples/zkapps/dex/upgradability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) {
});
await tx.prove();

await expect(tx.sign([feePayerKey, keys.dex]).send()).rejects.toThrow(
/Cannot update field 'delegate'/
);
await expect(
tx.sign([feePayerKey, keys.dex]).sendOrThrowIfError()
).rejects.toThrow(/Cannot update field 'delegate'/);

console.log('changing delegate permission back to normal');

Expand Down Expand Up @@ -185,9 +185,9 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) {
fieldUpdate.requireSignature();
});
await tx.prove();
await expect(tx.sign([feePayerKey, keys.dex]).send()).rejects.toThrow(
/Cannot update field 'delegate'/
);
await expect(
tx.sign([feePayerKey, keys.dex]).sendOrThrowIfError()
).rejects.toThrow(/Cannot update field 'delegate'/);

/**
* # Atomic Actions 3
Expand Down Expand Up @@ -461,9 +461,9 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) {
modifiedDex.deploy(); // cannot deploy new VK because its forbidden
});
await tx.prove();
await expect(tx.sign([feePayerKey, keys.dex]).send()).rejects.toThrow(
/Cannot update field 'verificationKey'/
);
await expect(
tx.sign([feePayerKey, keys.dex]).sendOrThrowIfError()
).rejects.toThrow(/Cannot update field 'verificationKey'/);

console.log('trying to invoke modified swap method');
// method should still be valid since the upgrade was forbidden
Expand Down
8 changes: 4 additions & 4 deletions src/examples/zkapps/hello-world/run-live.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ let transaction = await Mina.transaction(
transaction.sign([senderKey, zkAppKey]);
console.log('Sending the transaction.');
let pendingTx = await transaction.send();
if (pendingTx.hash() !== undefined) {
if (pendingTx.hash !== undefined) {
console.log(`Success! Deploy transaction sent.
Your smart contract will be deployed
as soon as the transaction is included in a block.
Txn hash: ${pendingTx.hash()}`);
Txn hash: ${pendingTx.hash}`);
}
console.log('Waiting for transaction inclusion in a block.');
await pendingTx.wait({ maxAttempts: 90 });
Expand All @@ -77,11 +77,11 @@ transaction = await Mina.transaction({ sender, fee: transactionFee }, () => {
await transaction.sign([senderKey]).prove();
console.log('Sending the transaction.');
pendingTx = await transaction.send();
if (pendingTx.hash() !== undefined) {
if (pendingTx.hash !== undefined) {
console.log(`Success! Update transaction sent.
Your smart contract state will be updated
as soon as the transaction is included in a block.
Txn hash: ${pendingTx.hash()}`);
Txn hash: ${pendingTx.hash}`);
}
console.log('Waiting for transaction inclusion in a block.');
await pendingTx.wait({ maxAttempts: 90 });
Expand Down
16 changes: 8 additions & 8 deletions src/examples/zkapps/hello-world/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ txn = await Mina.transaction(feePayer1.publicKey, () => {
AccountUpdate.fundNewAccount(feePayer1.publicKey);
zkAppInstance.deploy();
});
await txn.sign([feePayer1.privateKey, zkAppPrivateKey]).send();
await txn.sign([feePayer1.privateKey, zkAppPrivateKey]).sendOrThrowIfError();
MartinMinkov marked this conversation as resolved.
Show resolved Hide resolved

const initialState =
Mina.getAccount(zkAppAddress).zkapp?.appState?.[0].toString();
Expand All @@ -45,7 +45,7 @@ txn = await Mina.transaction(feePayer1.publicKey, () => {
zkAppInstance.update(Field(4), adminPrivateKey);
});
await txn.prove();
await txn.sign([feePayer1.privateKey]).send();
await txn.sign([feePayer1.privateKey]).sendOrThrowIfError();

currentState = Mina.getAccount(zkAppAddress).zkapp?.appState?.[0].toString();

Expand All @@ -70,7 +70,7 @@ try {
zkAppInstance.update(Field(16), wrongAdminPrivateKey);
});
await txn.prove();
await txn.sign([feePayer1.privateKey]).send();
await txn.sign([feePayer1.privateKey]).sendOrThrowIfError();
} catch (err: any) {
handleError(err, 'Account_delegate_precondition_unsatisfied');
}
Expand All @@ -91,7 +91,7 @@ try {
zkAppInstance.update(Field(30), adminPrivateKey);
});
await txn.prove();
await txn.sign([feePayer1.privateKey]).send();
await txn.sign([feePayer1.privateKey]).sendOrThrowIfError();
} catch (err: any) {
handleError(err, 'assertEquals');
}
Expand All @@ -118,7 +118,7 @@ try {
}
);
await txn.prove();
await txn.sign([feePayer1.privateKey]).send();
await txn.sign([feePayer1.privateKey]).sendOrThrowIfError();
} catch (err: any) {
handleError(err, 'assertEquals');
}
Expand All @@ -134,7 +134,7 @@ txn2 = await Mina.transaction({ sender: feePayer2.publicKey, fee: '2' }, () => {
zkAppInstance.update(Field(16), adminPrivateKey);
});
await txn2.prove();
await txn2.sign([feePayer2.privateKey]).send();
await txn2.sign([feePayer2.privateKey]).sendOrThrowIfError();

currentState = Mina.getAccount(zkAppAddress).zkapp?.appState?.[0].toString();

Expand All @@ -151,7 +151,7 @@ txn3 = await Mina.transaction({ sender: feePayer3.publicKey, fee: '1' }, () => {
zkAppInstance.update(Field(256), adminPrivateKey);
});
await txn3.prove();
await txn3.sign([feePayer3.privateKey]).send();
await txn3.sign([feePayer3.privateKey]).sendOrThrowIfError();

currentState = Mina.getAccount(zkAppAddress).zkapp?.appState?.[0].toString();

Expand All @@ -174,7 +174,7 @@ try {
}
);
await txn4.prove();
await txn4.sign([feePayer4.privateKey]).send();
await txn4.sign([feePayer4.privateKey]).sendOrThrowIfError();
} catch (err: any) {
handleError(err, 'assertEquals');
}
Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ export {
} from './lib/provable-types/merkle-list.js';

export * as Mina from './lib/mina.js';
export {
type Transaction,
type PendingTransaction,
type IncludedTransaction,
type RejectedTransaction,
} from './lib/mina/transaction.js';
export type { DeployArgs } from './lib/zkapp.js';
export {
SmartContract,
Expand Down Expand Up @@ -82,7 +88,7 @@ export {
export { TokenAccountUpdateIterator } from './lib/mina/token/forest-iterator.js';
export { TokenContract } from './lib/mina/token/token-contract.js';

export type { TransactionStatus } from './lib/fetch.js';
export type { TransactionStatus } from './lib/mina/graphql.js';
export {
fetchAccount,
fetchLastBlock,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/account-update.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function createAccountUpdate() {
AccountUpdate.fundNewAccount(feePayer);
});
tx.sign();
await expect(tx.send()).rejects.toThrow(
await expect(tx.sendOrThrowIfError()).rejects.toThrow(
'Check signature: Invalid signature on fee payer for key'
);
}
2 changes: 1 addition & 1 deletion src/lib/caller.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ let tx = await Mina.transaction(privateKey, () => {
});

// according to this test, the child doesn't get token permissions
await expect(tx.send()).rejects.toThrow(
await expect(tx.sendOrThrowIfError()).rejects.toThrow(
'can not use or pass on token permissions'
);
Loading
Loading