o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
88 lines (75 loc) • 2.72 kB
text/typescript
import {
method,
Mina,
AccountUpdate,
SmartContract,
UInt64,
Permissions,
} from 'o1js';
class PaymentContainer extends SmartContract {
init() {
super.init();
this.account.permissions.set({
...Permissions.default(),
send: Permissions.proofOrSignature(),
});
}
async withdraw(amount: UInt64) {
// unconstrained because we don't care where the user wants to withdraw to
let to = this.sender.getUnconstrained();
this.send({ to, amount });
}
async deposit(amount: UInt64) {
let sender = this.sender.getUnconstrained(); // unconstrained because we're already requiring a signature in the next line
let senderUpdate = AccountUpdate.createSigned(sender);
senderUpdate.send({ to: this, amount });
}
}
let proofsEnabled = false;
if (proofsEnabled) await PaymentContainer.compile();
let Local = await Mina.LocalBlockchain({ proofsEnabled });
Mina.setActiveInstance(Local);
// a test account that pays all the fees, and puts additional funds into the zkapp
const [feePayer] = Local.testAccounts;
const [contractAccount, account1, account2] = Mina.TestPublicKey.random(3);
function printBalances() {
console.log(
`zkApp balance: ${Mina.getBalance(contractAccount).div(1e9)} MINA`
);
console.log(`account1 balance: ${Mina.getBalance(account1).div(1e9)} MINA`);
console.log(`account2 balance: ${Mina.getBalance(account2).div(1e9)} MINA\n`);
}
let zkapp = new PaymentContainer(contractAccount);
let tx;
console.log('deploy and fund user accounts');
tx = await Mina.transaction(feePayer, async () => {
let feePayerUpdate = AccountUpdate.fundNewAccount(feePayer, 3);
feePayerUpdate.send({ to: account1, amount: 2e9 });
feePayerUpdate.send({ to: account2, amount: 0 }); // just touch account #2, so it's created
await zkapp.deploy();
});
await tx.sign([feePayer.key, contractAccount.key]).send();
printBalances();
console.log('---------- deposit MINA into zkApp (with proof) ----------');
tx = await Mina.transaction(account1, async () => {
await zkapp.deposit(UInt64.from(1e9));
});
await tx.prove();
await tx.sign([account1.key]).send();
printBalances();
console.log('---------- send MINA from zkApp (with proof) ----------');
tx = await Mina.transaction(account1, async () => {
await zkapp.withdraw(UInt64.from(1e9));
});
await tx.prove();
await tx.sign([account1.key]).send();
printBalances();
console.log(
'---------- send MINA between accounts (with signature) ----------'
);
tx = await Mina.transaction(account1, async () => {
let account1Update = AccountUpdate.createSigned(account1);
account1Update.send({ to: account2, amount: 1e9 });
});
await tx.sign([account1.key]).send();
printBalances();