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

Tokens #273

Merged
merged 51 commits into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f9ae535
feat: Add transfer of custom tokens naively
MartinMinkov Jun 25, 2022
980c1d8
Mess around with Parties
MartinMinkov Jul 5, 2022
7ddbaa2
feat: Add token class
MartinMinkov Jul 5, 2022
c9ebc35
this.token.transfer successfully changes balances with public key input
MartinMinkov Jul 6, 2022
c5a34d5
feat: Brute force custom token transfer
MartinMinkov Jul 6, 2022
c87de4c
Change createUnsigned to use optional object parameter for tokens
MartinMinkov Jul 6, 2022
4d44977
Remove old transfer
MartinMinkov Jul 6, 2022
25b06b7
Use Bool() for account creation fee for token accounts
MartinMinkov Jul 7, 2022
74bbd4f
Add basic mint/burn methods
MartinMinkov Jul 8, 2022
432abc1
wip: burn and transfer pass transaction logic
MartinMinkov Jul 11, 2022
a94b68b
Set lazy-signature for required parties in token transfers
MartinMinkov Jul 11, 2022
f5cb144
Fix spelling in sign function
MartinMinkov Jul 11, 2022
1b4b990
Add token id in Ledger.getAccount
MartinMinkov Jul 12, 2022
0bd67fd
Remove newTokenAccount in favor of using Party.fundNewAccount()
MartinMinkov Jul 12, 2022
9717a51
Change this.token to a function to take optional token id
MartinMinkov Jul 12, 2022
4dde4ff
Add token in getAccount
MartinMinkov Jul 12, 2022
b1f5867
Refactor this.token().transfer to this.token().send()
MartinMinkov Jul 12, 2022
753ce86
Use getBalance for fetching balance from local ledger
MartinMinkov Jul 12, 2022
b353132
Remove comment code
MartinMinkov Jul 13, 2022
c8aa6cc
Add tokenId to getAccount
MartinMinkov Jul 13, 2022
728a132
Refactor createUnsigned to take string instead of Field for caller an…
MartinMinkov Jul 14, 2022
4383060
Add proper typing for snarkyjs binding token functions
MartinMinkov Jul 14, 2022
5a1dbe6
Add tokenSymbol to Party API
MartinMinkov Jul 14, 2022
d78353c
Fix getCachedAccount by passing in tokenId
MartinMinkov Jul 14, 2022
66432c4
Fix usage of fetchAccount
MartinMinkov Jul 14, 2022
ef8267c
Fix tokenSymbol setter
MartinMinkov Jul 15, 2022
335b551
Scaffold test file for tokens
MartinMinkov Jul 15, 2022
ad3e967
Add first section of token tests, refactor existing Party token code
MartinMinkov Jul 15, 2022
6f7191e
Add minting with precondition tests
MartinMinkov Jul 15, 2022
f0c2d72
Refactor getAccount and getBalance parameters
MartinMinkov Jul 18, 2022
ece0c82
Implement burn and send tests
MartinMinkov Jul 18, 2022
6ff6785
Fix fetchAccount type parameters
MartinMinkov Jul 18, 2022
f5178ce
Use init method for zkApp state
MartinMinkov Jul 18, 2022
d94b75f
Add support for checked tokenId, convert tokenId type to Field, addit…
MartinMinkov Jul 19, 2022
48c9101
Refactor checked computation check and error messages
MartinMinkov Jul 19, 2022
4802f95
Update bindings
MartinMinkov Jul 19, 2022
cc3d690
PR feedback
MartinMinkov Jul 19, 2022
92be6a4
Fix parentTokenId parameter for new Token()
MartinMinkov Jul 20, 2022
3f78945
Add getter for tokenId on Party structure
MartinMinkov Jul 20, 2022
1225452
Update bindings
MartinMinkov Jul 20, 2022
fe55f6e
Fix CircuitValue.isConstant
MartinMinkov Jul 20, 2022
c359962
Update for isNew
MartinMinkov Jul 20, 2022
d870ae1
Fix intg tests
MartinMinkov Jul 21, 2022
39281e7
Merge branch 'main' into test/tokens-playground
MartinMinkov Jul 21, 2022
e73a4f6
Use createChildParty instead of createUnsigned
MartinMinkov Jul 21, 2022
903a860
Merge branch 'main' into test/tokens-playground
MartinMinkov Jul 21, 2022
8203973
Add formatted getAccount error
MartinMinkov Jul 22, 2022
dc19579
Fix checked and unchecked condition in token constructor
MartinMinkov Jul 22, 2022
4788a9a
Fix GraphQL query parameter
MartinMinkov Jul 22, 2022
997eecd
integrate `deploy()` with qanet
mitschabaude May 10, 2022
c0035b6
fix integration test
mitschabaude Jul 25, 2022
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
2 changes: 1 addition & 1 deletion MINA_COMMIT
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The mina commit used to generate the backends for node and chrome is
97ff72a1d43cda02225d972031cdb0639f0abf84
dea7b89becac85444610378dd579ea0216631349
2 changes: 1 addition & 1 deletion src/examples/deploy/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isReady, PrivateKey, deploy, shutdown, compile } from 'snarkyjs';
import { isReady, PrivateKey, deploy, shutdown } from 'snarkyjs';
import SimpleZkapp from './simple_zkapp';
import { readFileSync, existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
Expand Down
9 changes: 7 additions & 2 deletions src/examples/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import {
setGraphqlEndpoint,
shutdown,
fetchLastBlock,
PublicKey,
} from 'snarkyjs';

await isReady;
setGraphqlEndpoint('https://proxy.berkeley.minaexplorer.com/graphql');

let zkappAddress = 'B62qpRzFVjd56FiHnNfxokVbcHMQLT119My1FEdSq8ss7KomLiSZcan';
let { account, error } = await fetchAccount(zkappAddress);
let zkappAddress = PublicKey.fromBase58(
'B62qpRzFVjd56FiHnNfxokVbcHMQLT119My1FEdSq8ss7KomLiSZcan'
);
let { account, error } = await fetchAccount({
publicKey: zkappAddress,
});
console.log('account', JSON.stringify(account, null, 2));
console.log('error', error);

Expand Down
2 changes: 1 addition & 1 deletion src/examples/simple_zkapp_berkeley.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Mina.setActiveInstance(Berkeley);
let feePayerKey = PrivateKey.fromBase58(
'EKEQc95PPQZnMY9d9p1vq1MWLeDJKtvKj4V75UDG3rjnf32BerWD'
);
let response = await fetchAccount(feePayerKey.toPublicKey());
let response = await fetchAccount({ publicKey: feePayerKey.toPublicKey() });
if (response.error) throw Error(response.error.statusText);
let { nonce, balance } = response.account;
console.log(`Using fee payer account with nonce ${nonce}, balance ${balance}`);
Expand Down
9 changes: 8 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@ export {
} from './lib/zkapp';
export { state, State, declareState } from './lib/state';
export { Proof, SelfProof, ZkProgram, verify } from './lib/proof_system';
export { Party, Permissions, ZkappPublicInput } from './lib/party';
export {
Token,
Party,
Permissions,
ZkappPublicInput,
getDefaultTokenId,
partiesToJson,
} from './lib/party';
export {
fetchAccount,
fetchLastBlock,
Expand Down
82 changes: 63 additions & 19 deletions src/lib/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import 'isomorphic-fetch';
import { Bool, Field, Types } from '../snarky';
import { Bool, Field, Types, Ledger } from '../snarky';
import { UInt32, UInt64 } from './int';
import { Permission, Permissions, ZkappStateLength } from './party';
import {
getDefaultTokenId,
Permission,
Permissions,
ZkappStateLength,
} from './party';
import { PublicKey } from './signature';
import { NetworkValue } from './precondition';

Expand Down Expand Up @@ -41,18 +46,24 @@ function setGraphqlEndpoint(graphqlEndpoint: string) {
* @returns zkapp information on the specified account or an error is thrown
*/
async function fetchAccount(
publicKey: string | PublicKey,
accountInfo: { publicKey: string | PublicKey; tokenId?: string },
graphqlEndpoint = defaultGraphqlEndpoint,
{ timeout = defaultTimeout } = {}
): Promise<
| { account: Account; error: undefined }
| { account: undefined; error: FetchError }
> {
let publicKeyBase58 =
publicKey instanceof PublicKey ? publicKey.toBase58() : publicKey;
let response = await fetchAccountInternal(publicKeyBase58, graphqlEndpoint, {
timeout,
});
accountInfo.publicKey instanceof PublicKey
? accountInfo.publicKey.toBase58()
: accountInfo.publicKey;
let response = await fetchAccountInternal(
{ publicKey: publicKeyBase58, tokenId: accountInfo.tokenId },
graphqlEndpoint,
{
timeout,
}
);
return response.error === undefined
? {
account: parseFetchedAccount(response.account),
Expand All @@ -64,12 +75,16 @@ async function fetchAccount(
// internal version of fetchAccount which does the same, but returns the original JSON version
// of the account, to save some back-and-forth conversions when caching accounts
async function fetchAccountInternal(
publicKey: string,
accountInfo: { publicKey: string; tokenId?: string },
graphqlEndpoint = defaultGraphqlEndpoint,
config?: FetchConfig
) {
const { publicKey, tokenId } = accountInfo;
let [response, error] = await makeGraphqlRequest(
accountQuery(publicKey),
accountQuery(
publicKey,
tokenId ?? Ledger.fieldToBase58(getDefaultTokenId())
),
graphqlEndpoint,
config
);
Expand Down Expand Up @@ -123,6 +138,8 @@ function toPermission(p: AuthRequired): Permission {
type FetchedAccount = {
publicKey: string;
nonce: string;
tokenId: string;
tokenSymbol: string;
zkappUri?: string;
zkappState: string[] | null;
receiptChainHash?: string;
Expand All @@ -149,6 +166,8 @@ type Account = {
publicKey: PublicKey;
nonce: UInt32;
balance: UInt64;
tokenId: Field;
tokenSymbol: string;
zkapp?: { appState: Field[] };
permissions?: Permissions;
receiptChainHash?: Field;
Expand All @@ -160,13 +179,15 @@ type Account = {
type FlexibleAccount = {
publicKey: PublicKey | string;
nonce: UInt32 | string | number;
tokenId?: string;
tokenSymbol?: string;
balance?: UInt64 | string | number;
zkapp?: { appState: (Field | string | number)[] };
};

// TODO provedState
const accountQuery = (publicKey: string) => `{
account(publicKey: "${publicKey}") {
const accountQuery = (publicKey: string, tokenId: string) => `{
account(publicKey: "${publicKey}", tokenId: "${tokenId}") {
publicKey
nonce
zkappUri
Expand All @@ -188,6 +209,8 @@ const accountQuery = (publicKey: string) => `{
balance { total }
delegateAccount { publicKey }
sequenceEvents
tokenId
tokenSymbol
}
}
`;
Expand All @@ -206,6 +229,8 @@ function parseFetchedAccount({
delegateAccount,
receiptChainHash,
sequenceEvents,
tokenId,
tokenSymbol,
}: Partial<FetchedAccount>): Partial<Account> {
return {
publicKey:
Expand All @@ -228,11 +253,13 @@ function parseFetchedAccount({
// : undefined,
delegate:
delegateAccount && PublicKey.fromBase58(delegateAccount.publicKey),
tokenId: tokenId !== undefined ? Ledger.fieldOfBase58(tokenId) : undefined,
tokenSymbol: tokenSymbol !== undefined ? tokenSymbol : undefined,
};
}

function stringifyAccount(account: FlexibleAccount): FetchedAccount {
let { publicKey, nonce, balance, zkapp } = account;
let { publicKey, nonce, balance, zkapp, tokenId, tokenSymbol } = account;
return {
publicKey:
publicKey instanceof PublicKey ? publicKey.toBase58() : publicKey,
Expand All @@ -241,6 +268,8 @@ function stringifyAccount(account: FlexibleAccount): FetchedAccount {
zkapp?.appState.map((s) => s.toString()) ??
Array(ZkappStateLength).fill('0'),
balance: { total: balance?.toString() ?? '0' },
tokenId: tokenId ?? Ledger.fieldToBase58(getDefaultTokenId()),
tokenSymbol: tokenSymbol ?? '',
};
}

Expand All @@ -262,15 +291,21 @@ let networkCache = {} as Record<
>;
let accountsToFetch = {} as Record<
string,
{ publicKey: string; graphqlEndpoint: string }
{ publicKey: string; tokenId: string; graphqlEndpoint: string }
>;
let networksToFetch = {} as Record<string, { graphqlEndpoint: string }>;
let cacheExpiry = 10 * 60 * 1000; // 10 minutes

function markAccountToBeFetched(publicKey: PublicKey, graphqlEndpoint: string) {
function markAccountToBeFetched(
publicKey: PublicKey,
tokenId: Field,
graphqlEndpoint: string
) {
let publicKeyBase58 = publicKey.toBase58();
accountsToFetch[`${publicKeyBase58};${graphqlEndpoint}`] = {
let tokenBase58 = Ledger.fieldToBase58(tokenId);
accountsToFetch[`${publicKeyBase58};${tokenBase58};${graphqlEndpoint}`] = {
publicKey: publicKeyBase58,
tokenId: tokenBase58,
graphqlEndpoint,
};
}
Expand All @@ -285,8 +320,11 @@ async function fetchMissingData(graphqlEndpoint: string) {
let cachedAccount = accountCache[key];
return cachedAccount === undefined || cachedAccount.timestamp < expired;
});
let promises = accounts.map(async ([key, { publicKey }]) => {
let response = await fetchAccountInternal(publicKey, graphqlEndpoint);
let promises = accounts.map(async ([key, { publicKey, tokenId }]) => {
let response = await fetchAccountInternal(
{ publicKey, tokenId },
graphqlEndpoint
);
if (response.error === undefined) delete accountsToFetch[key];
});

Expand All @@ -311,10 +349,15 @@ async function fetchMissingData(graphqlEndpoint: string) {

function getCachedAccount(
publicKey: PublicKey,
tokenId: Field,
graphqlEndpoint = defaultGraphqlEndpoint
) {
let account =
accountCache[`${publicKey.toBase58()};${graphqlEndpoint}`]?.account;
accountCache[
`${publicKey.toBase58()};${Ledger.fieldToBase58(
tokenId
)};${graphqlEndpoint}`
]?.account;
if (account !== undefined) return parseFetchedAccount(account);
}
function getCachedNetwork(graphqlEndpoint = defaultGraphqlEndpoint) {
Expand All @@ -329,6 +372,7 @@ function addCachedAccount(
zkapp?: {
appState: (string | number | Field)[];
};
tokenId: string;
},
graphqlEndpoint = defaultGraphqlEndpoint
) {
Expand All @@ -339,7 +383,7 @@ function addCachedAccountInternal(
account: FetchedAccount,
graphqlEndpoint: string
) {
accountCache[`${account.publicKey};${graphqlEndpoint}`] = {
accountCache[`${account.publicKey};${account.tokenId};${graphqlEndpoint}`] = {
account,
graphqlEndpoint,
timestamp: Date.now(),
Expand Down
2 changes: 1 addition & 1 deletion src/lib/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { inCheckedComputation } from './proof_system';
export { Poseidon };

// internal API
export { prefixes, emptyHashWithPrefix, hashWithPrefix };
export { prefixes, emptyHashWithPrefix, hashWithPrefix, salt };

class Sponge {
private sponge: unknown;
Expand Down
Loading