diff --git a/src/lib/mina.ts b/src/lib/mina.ts index 40a47e589e..0582d45ffa 100644 --- a/src/lib/mina.ts +++ b/src/lib/mina.ts @@ -65,7 +65,7 @@ function setCurrentTransaction(transaction: CurrentTransaction) { type SenderSpec = | PrivateKey - | { feePayerKey: PrivateKey; fee?: number | string | UInt64 } + | { feePayerKey: PrivateKey; fee?: number | string | UInt64; memo?: string } | undefined; function createUnsignedTransaction( @@ -76,10 +76,7 @@ function createUnsignedTransaction( } function createTransaction( - feePayer: - | PrivateKey - | { feePayerKey: PrivateKey; fee?: number | string | UInt64 } - | undefined, + feePayer: SenderSpec, f: () => unknown, { fetchMode = 'cached' as FetchMode } = {} ): Transaction { @@ -89,6 +86,7 @@ function createTransaction( let feePayerKey = feePayer instanceof PrivateKey ? feePayer : feePayer?.feePayerKey; let fee = feePayer instanceof PrivateKey ? undefined : feePayer?.fee; + let memo = feePayer instanceof PrivateKey ? '' : feePayer?.memo ?? ''; currentTransaction = { sender: feePayerKey, @@ -127,6 +125,7 @@ function createTransaction( let transaction: Parties = { otherParties: currentTransaction.parties, feePayer: feePayerParty, + memo, }; nextTransactionId.value += 1; diff --git a/src/lib/party.ts b/src/lib/party.ts index efb69dd7ad..3aa538549e 100644 --- a/src/lib/party.ts +++ b/src/lib/party.ts @@ -744,10 +744,12 @@ class Party { type Parties = { feePayer: FeePayerUnsigned; otherParties: Party[]; + memo: string; }; type PartiesSigned = { feePayer: FeePayer; otherParties: (Party & { authorization: Control | LazyProof })[]; + memo: string; }; // TODO: probably shouldn't hard-code dummy signature @@ -771,15 +773,16 @@ function toPartyUnsafe({ body, authorization }: Party): Types.Party { function toPartiesUnsafe({ feePayer, otherParties, + memo, }: { feePayer: FeePayerUnsigned; otherParties: Party[]; + memo: string; }): Types.Parties { return { feePayer: toFeePayerUnsafe(feePayer), otherParties: otherParties.map(toPartyUnsafe), - // TODO expose to Mina.transaction - memo: Ledger.memoToBase58(''), + memo: Ledger.memoToBase58(memo), }; } @@ -842,16 +845,18 @@ function addMissingSignatures( party.authorization = { signature }; return party as P & { authorization: Control }; } - let { feePayer, otherParties } = parties; + let { feePayer, otherParties, memo } = parties; return { feePayer: addFeePayerSignature(feePayer), otherParties: otherParties.map((p) => addSignature(p)), + memo, }; } type PartiesProved = { feePayer: FeePayerUnsigned; otherParties: (Party & { authorization: Control | LazySignature })[]; + memo: string; }; async function addMissingProofs(parties: Parties): Promise { @@ -889,7 +894,7 @@ async function addMissingProofs(parties: Parties): Promise { party.authorization = { proof: Pickles.proofToString(proof) }; return party as P & { authorization: Control | LazySignature }; } - let { feePayer, otherParties } = parties; + let { feePayer, otherParties, memo } = parties; // compute proofs serially. in parallel would clash with our global variable hacks let otherPartiesProved: (Party & { authorization: Control | LazySignature; @@ -898,7 +903,7 @@ async function addMissingProofs(parties: Parties): Promise { let partyProved = await addProof(otherParties[i], i); otherPartiesProved.push(partyProved); } - return { feePayer, otherParties: otherPartiesProved }; + return { feePayer, otherParties: otherPartiesProved, memo }; } /** diff --git a/src/lib/zkapp.ts b/src/lib/zkapp.ts index 8e394418c0..77f80172f9 100644 --- a/src/lib/zkapp.ts +++ b/src/lib/zkapp.ts @@ -656,6 +656,7 @@ async function deploy( feePayerKey, transactionFee, feePayerNonce, + memo, }: { zkappKey: PrivateKey; verificationKey: { data: string; hash: string | Field }; @@ -664,6 +665,7 @@ async function deploy( shouldSignFeePayer?: boolean; transactionFee?: string | number; feePayerNonce?: string | number; + memo?: string; } ) { let address = zkappKey.toPublicKey(); @@ -698,6 +700,7 @@ async function deploy( zkapp.self.balance.addInPlace(amount); } }); + tx.transaction.memo = memo ?? ''; if (shouldSignFeePayer) { if (feePayerKey === undefined || transactionFee === undefined) { throw Error( @@ -767,11 +770,12 @@ async function callUnproved( } function addFeePayer( - { feePayer, otherParties }: Parties, + { feePayer, otherParties, memo }: Parties, feePayerKey: PrivateKey | string, { transactionFee = 0 as number | string, feePayerNonce = undefined as number | string | undefined, + memo: feePayerMemo = undefined as string | undefined, } ) { feePayer = cloneCircuitValue(feePayer); @@ -782,11 +786,13 @@ function addFeePayer( let senderAccount = Mina.getAccount(senderAddress); feePayerNonce = senderAccount.nonce.toString(); } + let newMemo = memo; + if (feePayerMemo) newMemo = Ledger.memoToBase58(feePayerMemo); feePayer.body.nonce = UInt32.fromString(`${feePayerNonce}`); feePayer.body.publicKey = senderAddress; feePayer.body.fee = UInt64.fromString(`${transactionFee}`); Party.signFeePayerInPlace(feePayer, feePayerKey); - return { feePayer, otherParties }; + return { feePayer, otherParties, memo: newMemo }; } function signFeePayer( @@ -795,6 +801,7 @@ function signFeePayer( { transactionFee = 0 as number | string, feePayerNonce = undefined as number | string | undefined, + memo: feePayerMemo = undefined as string | undefined, } ) { let parties: Types.Json.Parties = JSON.parse(transactionJson); @@ -805,6 +812,7 @@ function signFeePayer( let senderAccount = Mina.getAccount(senderAddress); feePayerNonce = senderAccount.nonce.toString(); } + if (feePayerMemo) parties.memo = Ledger.memoToBase58(feePayerMemo); parties.feePayer.body.nonce = `${feePayerNonce}`; parties.feePayer.body.publicKey = Ledger.publicKeyToString(senderAddress); parties.feePayer.body.fee = `${transactionFee}`;