Skip to content

Commit

Permalink
feat: contract for single on-chain wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg committed Jul 5, 2022
1 parent b417e63 commit 74945ea
Show file tree
Hide file tree
Showing 20 changed files with 518 additions and 22 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test-all-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ jobs:
run: cd packages/assert && yarn ${{ steps.vars.outputs.test }}
- name: yarn test (wallet/api)
run: cd packages/wallet/api && yarn ${{ steps.vars.outputs.test }}
- name: yarn test (wallet/contract)
run: cd packages/wallet/contract && yarn ${{ steps.vars.outputs.test }}
- name: yarn test (deployment)
run: cd packages/deployment && yarn ${{ steps.vars.outputs.test }}
- name: yarn test (ERTP)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"golang/cosmos",
"packages/*",
"packages/wallet/api",
"packages/wallet/contract",
"packages/wallet/ui"
],
"type": "module",
Expand Down
1 change: 1 addition & 0 deletions packages/agoric-cli/src/sdk-package-names.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default [
"@agoric/run-protocol",
"@agoric/same-structure",
"@agoric/sharing-service",
"@agoric/smart-wallet",
"@agoric/solo",
"@agoric/sparse-ints",
"@agoric/spawner",
Expand Down
4 changes: 4 additions & 0 deletions packages/casting/src/follower-cosmjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ export const makeCosmjsFollower = (
const getProvenValue = () => getProvenValueAtHeight(allegedBlockHeight);

const buf = await queryVerifier(getProvenValue, crash, getAllegedValue);
if (buf.length === 0) {
fail(Error('No query results'));
return;
}
attempt = 0;
if (!committer.isValid()) {
return;
Expand Down
6 changes: 3 additions & 3 deletions packages/vats/decentral-core-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@
"sharing": {
"sourceSpec": "@agoric/vats/src/vat-sharing.js"
},
"walletManager": {
"sourceSpec": "@agoric/vats/src/vat-walletManager.js"
"singleWallet": {
"sourceSpec": "@agoric/wallet/contract/src/singleWallet.js"
},
"zoe": {
"sourceSpec": "@agoric/vats/src/vat-zoe.js"
}
},
"defaultManagerType": "xs-worker"
}
}
6 changes: 3 additions & 3 deletions packages/vats/decentral-demo-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@
"sharing": {
"sourceSpec": "@agoric/vats/src/vat-sharing.js"
},
"walletManager": {
"sourceSpec": "@agoric/vats/src/vat-walletManager.js"
"singleWallet": {
"sourceSpec": "@agoric/wallet/contract/src/singleWallet.js"
},
"zoe": {
"sourceSpec": "@agoric/vats/src/vat-zoe.js"
}
},
"defaultManagerType": "xs-worker"
}
}
4 changes: 4 additions & 0 deletions packages/vats/scripts/build-bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const dirname = url.fileURLToPath(new URL('.', import.meta.url));
const sourceToBundle = [
[`../src/centralSupply.js`, `../bundles/bundle-centralSupply.js`],
[`../src/mintHolder.js`, `../bundles/bundle-mintHolder.js`],
[
`@agoric/wallet/contract/src/singleWallet.js`,
`../bundles/bundle-singleWallet.js`,
],
];

createBundles(sourceToBundle, dirname);
37 changes: 34 additions & 3 deletions packages/vats/src/core/basic-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,39 @@ export const makeAddressNameHubs = async ({
harden(makeAddressNameHubs);

/** @param {BootstrapSpace} powers */
export const makeClientBanks = async ({ consume: { client, bankManager } }) => {
export const makeClientBanks = async ({
consume: {
agoricNames,
board,
namesByAddress,
namesByAddressAdmin,
client,
chainStorage,
bankManager,
zoe,
},
installation: {
consume: { singleWallet },
},
}) => {
const STORAGE_PATH = 'wallet';

const storageNode = await getChildNode(chainStorage, STORAGE_PATH);
const marshaller = E(board).getPublishingMarshaller();
return E(client).assignBundle([
address => ({ bank: E(bankManager).getBankForAddress(address) }),
address => {
const bank = E(bankManager).getBankForAddress(address);
const myAddressNameAdmin = E(namesByAddressAdmin).lookupAdmin(address);
const smartWallet = E(zoe).startInstance(
singleWallet,
{},
{ agoricNames, bank, namesByAddress, myAddressNameAdmin, board },
{ storageNode, marshaller },
);

// sets these values in REPL home by way of registerWallet
return { bank, smartWallet };
},
]);
};
harden(makeClientBanks);
Expand All @@ -237,12 +267,13 @@ export const installBootContracts = async ({
devices: { vatAdmin },
consume: { zoe },
installation: {
produce: { centralSupply, mintHolder },
produce: { centralSupply, mintHolder, singleWallet },
},
}) => {
for (const [name, producer] of Object.entries({
centralSupply,
mintHolder,
singleWallet,
})) {
const bundleCap = D(vatAdmin).getNamedBundleCap(name);
const bundle = D(bundleCap).getBundle();
Expand Down
8 changes: 8 additions & 0 deletions packages/vats/src/core/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,16 @@ const SHARED_CHAIN_BOOTSTRAP_MANIFEST = harden({
},
makeClientBanks: {
consume: {
agoricNames: true,
namesByAddress: true,
namesByAddressAdmin: true,
bankManager: 'bank',
board: 'board',
client: true,
chainStorage: true,
zoe: 'zoe',
},
installation: { consume: { singleWallet: 'zoe' } },
home: { produce: { bank: 'bank' } },
},
installBootContracts: {
Expand All @@ -117,6 +124,7 @@ const SHARED_CHAIN_BOOTSTRAP_MANIFEST = harden({
produce: {
centralSupply: 'zoe',
mintHolder: 'zoe',
singleWallet: 'zoe',
},
},
},
Expand Down
3 changes: 2 additions & 1 deletion packages/vats/src/core/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@
* issuer: |
* 'RUN' | 'BLD' | 'Attestation' | 'AUSD',
* installation: |
* 'centralSupply' | 'mintHolder' | 'feeDistributor' |
* 'centralSupply' | 'mintHolder' | 'singleWallet' |
* 'feeDistributor' |
* 'contractGovernor' | 'committee' | 'noActionElectorate' | 'binaryVoteCounter' |
* 'amm' | 'VaultFactory' | 'liquidate' | 'runStake' |
* 'Pegasus' | 'reserve' | 'psm' | 'interchainPool',
Expand Down
1 change: 1 addition & 0 deletions packages/vats/src/core/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const agoricNamesReserved = harden({
installation: {
centralSupply: 'central supply',
mintHolder: 'mint holder',
singleWallet: 'single smart wallet',
contractGovernor: 'contract governor',
committee: 'committee electorate',
noActionElectorate: 'no action electorate',
Expand Down
5 changes: 4 additions & 1 deletion packages/vats/src/vat-walletManager.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { E, Far } from '@endo/far';
import walletBundle from '@agoric/wallet-backend/bundles/bundle-wallet.js';

export const buildRootObject = _vatPowers => {
/**
* @deprecated
*/
export const buildRootObject = () => {
return Far('walletManager root', {
buildWalletManager: vatAdminSvc =>
Far('walletManager', {
Expand Down
15 changes: 10 additions & 5 deletions packages/vats/test/devices.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import bundleCentralSupply from '../bundles/bundle-centralSupply.js';
import bundleMintHolder from '../bundles/bundle-mintHolder.js';
import bundleSingleWallet from '../bundles/bundle-singleWallet.js';

export const devices = {
vatAdmin: {
getNamedBundleCap: name => ({
getBundle: () => {
if (name === 'centralSupply') {
return bundleCentralSupply;
} else if (name === 'mintHolder') {
return bundleMintHolder;
switch (name) {
case 'centralSupply':
return bundleCentralSupply;
case 'mintHolder':
return bundleMintHolder;
case 'singleWallet':
return bundleSingleWallet;
default:
throw new Error(`unknown bundle ${name}`);
}
throw new Error(`unknown bundle ${name}`);
},
}),
},
Expand Down
32 changes: 26 additions & 6 deletions packages/vats/test/test-clientBundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ import {
} from '@agoric/run-protocol/src/proposals/demoIssuers.js';
import { makeClientManager } from '../src/core/chain-behaviors.js';
import { makeAgoricNamesAccess, makePromiseSpace } from '../src/core/utils.js';
import { buildRootObject as bldMintRoot } from '../src/vat-mints.js';
import { buildRootObject as mintsRoot } from '../src/vat-mints.js';
import { buildRootObject as boardRoot } from '../src/vat-board.js';
import {
installBootContracts,
makeAddressNameHubs,
makeBoard,
makeClientBanks,
} from '../src/core/basic-behaviors.js';

Expand All @@ -37,12 +40,16 @@ const setUpZoeForTest = async () => {
};
harden(setUpZoeForTest);

/**
* @typedef {{
* (n: 'board'): import('../src/core/basic-behaviors.js').BoardVat
* (n: 'mint'): MintsVat
* }} LoadVat
*/
test('connectFaucet produces payments', async t => {
const space = /** @type {any} */ (makePromiseSpace(t.log));
const { consume, produce } =
/** @type { BootstrapPowers & { consume: { loadVat: (n: 'mints') => MintsVat }} } */ (
space
);
/** @type { BootstrapPowers & { consume: { loadVat: LoadVat }} } */ (space);
const { agoricNames, spaces } = makeAgoricNamesAccess();
produce.agoricNames.resolve(agoricNames);

Expand All @@ -51,14 +58,22 @@ test('connectFaucet produces payments', async t => {
produce.feeMintAccess.resolve(feeMintAccess);

produce.loadVat.resolve(name => {
assert.equal(name, 'mints');
return bldMintRoot();
switch (name) {
case 'mints':
return mintsRoot();
case 'board':
return boardRoot();
default:
throw Error('unknown loadVat name');
}
});

t.plan(4); // be sure bank.deposit() gets called

const bldKit = makeIssuerKit('BLD');
produce.bldIssuerKit.resolve(bldKit);
produce.chainStorage.resolve(undefined);

const runIssuer = E(zoe).getFeeIssuer();
produce.bankManager.resolve(
Promise.resolve(
Expand All @@ -76,6 +91,8 @@ test('connectFaucet produces payments', async t => {
return amt;
},
}),
// @ts-expect-error mock
getAssetSubscription: () => null,
}),
}),
),
Expand All @@ -98,6 +115,9 @@ test('connectFaucet produces payments', async t => {
};

await Promise.all([
// @ts-expect-error missing keys: devices, vats, vatPowers, vatParameters, and 2 more.
makeBoard({ consume, produce, ...spaces }),
makeAddressNameHubs({ consume, produce, ...spaces }),
installBootContracts({ vatPowers, devices, consume, produce, ...spaces }),
makeClientManager({ consume, produce, ...spaces }),
connectFaucet({ consume, produce, ...spaces }),
Expand Down
31 changes: 31 additions & 0 deletions packages/wallet/contract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Smart Wallet contracts

## Single contract

The `singleWalet` contract manages a single smart wallet.

# Multi-tenant contract

The `walletFactory` contract provisions and manages smart wallets.

# Common

There can be zero or one wallets per Cosmos address.

lib-wallet has makeWallet but that's really makeWalletKit

1. Generate an address (off-chain)
2. Provision an account using that address, which causes a Bank to get created
??? What happens if you try to provision again using the same address? It's a Cosmos level transaction; maybe that fails.
3. Create a Wallet using the Bank (it includes the implementation of Virtual Purses so when you getAmount it goes down to the Golang layer)
??? What happens if you try to create another wallet using that bank?

1 Address : 0/1 Bank
1 Address : 1 `myAddressNamesAdmin`
1 Bank : 0/1 Wallet

By design there's a 1:1 across all four.

`namesByAddress` and `board` are shared by everybody.

`myAddressNamesAdmin` is from the account you provision.
25 changes: 25 additions & 0 deletions packages/wallet/contract/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This file can contain .js-specific Typescript compiler config.
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",

"noEmit": true,
/*
// The following flags are for creating .d.ts files:
"noEmit": false,
"declaration": true,
"emitDeclarationOnly": true,
*/
"downlevelIteration": true,
"strictNullChecks": true,
"moduleResolution": "node",
},
"include": [
"*.js",
"scripts/**/*.js",
"src/**/*.js",
"test/**/*.js",
"tools/**/*.js",
],
}
Loading

0 comments on commit 74945ea

Please sign in to comment.