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

Add wallet support for decimal currencies and some examples #1984

Merged
merged 9 commits into from
Nov 5, 2020
Merged
82 changes: 55 additions & 27 deletions packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,60 @@ export function buildRootObject(vatPowers, vatParameters) {
]);

// Make the other demo mints
const issuerNames = ['moola', 'simolean'];
/**
* @typedef {Object} IssuerRecord
* @property {Array<any>} [issuerArgs]
* @property {string} pursePetname
* @property {any} mintValue
*/
/** @type {Map<string, IssuerRecord>} */
const issuerNameToRecord = new Map(
harden([
[
'Testnet.$USD',
{
issuerArgs: [undefined, { decimalPlaces: 3 }],
mintValue: 20000,
pursePetname: 'Local currency',
},
],
[
'Testnet.$LINK',
{
issuerArgs: [undefined, { decimalPlaces: 6 }],
mintValue: 7 * 10 ** 6,
pursePetname: 'Oracle fee',
},
],
[
'moola',
{
mintValue: 1900,
pursePetname: 'Fun budget',
},
],
[
'simolean',
{
mintValue: 1900,
pursePetname: 'Nest egg',
},
],
]),
);
const issuerNames = [...issuerNameToRecord.keys()];
const issuers = await Promise.all(
issuerNames.map(issuerName =>
E(vats.mints).makeMintAndIssuer(issuerName),
E(vats.mints).makeMintAndIssuer(
issuerName,
...(issuerNameToRecord.get(issuerName).issuerArgs || []),
),
),
);

// TODO: Create priceAuthority pairs for moola-simolean based on the
// FakePriceAuthority.

// Register the moola and simolean issuers
const issuerInfo = await Promise.all(
issuerNames.map(async (issuerName, i) =>
harden({
issuer: issuers[i],
petname: issuerName,
}),
),
);

return harden({
async createUserBundle(_nickname, powerFlags = []) {
// Bind to some fresh ports (unspecified name) on the IBC implementation
Expand All @@ -95,25 +129,19 @@ export function buildRootObject(vatPowers, vatParameters) {
additionalPowers.priceAuthorityAdmin = priceAuthorityAdmin;
}

const pursePetnames = {
moola: 'Fun budget',
simolean: 'Nest egg',
};

const payments = await E(vats.mints).mintInitialPayments(
issuerNames,
harden([1900, 1900]),
issuerNames.map(
issuerName => issuerNameToRecord.get(issuerName).mintValue,
),
);

const paymentInfo = issuerInfo.map(
({ petname: issuerPetname, issuer }, i) => ({
issuerPetname,
issuer,
payment: payments[i],
pursePetname:
pursePetnames[issuerPetname] || `${issuerPetname} purse`,
}),
);
const paymentInfo = issuerNames.map((issuerName, i) => ({
issuer: issuers[i],
issuerPetname: issuerName,
payment: payments[i],
pursePetname: issuerNameToRecord.get(issuerName).pursePetname,
}));

const faucet = {
// A method to reap the spoils of our on-chain provisioning.
Expand Down
7 changes: 5 additions & 2 deletions packages/cosmic-swingset/lib/ag-solo/vats/vat-mints.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ export function buildRootObject(_vatPowers) {
getMint: name => mintsAndMath.get(name).mint,
getMints: issuerNames => issuerNames.map(api.getMint),
// For example, issuerNameSingular might be 'moola', or 'simolean'
makeMintAndIssuer: issuerNameSingular => {
const { mint, issuer, amountMath } = makeIssuerKit(issuerNameSingular);
makeMintAndIssuer: (issuerNameSingular, ...issuerArgs) => {
const { mint, issuer, amountMath } = makeIssuerKit(
issuerNameSingular,
...issuerArgs,
);
mintsAndMath.init(issuerNameSingular, { mint, amountMath });
return issuer;
},
Expand Down
18 changes: 15 additions & 3 deletions packages/dapp-svelte-wallet/api/src/lib-wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ export async function makeWallet({
// We have a depositId for the purse.
depositBoardId = brandToDepositFacetId.get(brand);
}

const issuerRecord = brandTable.getByBrand(brand);
/**
* @type {PursesJSONState}
*/
Expand All @@ -158,21 +160,24 @@ export async function makeWallet({
...(depositBoardId && { depositBoardId }),
brandPetname,
pursePetname,
displayInfo: (issuerRecord && issuerRecord.displayInfo),
value,
currentAmountSlots: dehydratedCurrentAmount,
currentAmount: fillInSlots(dehydratedCurrentAmount),
};
pursesState.set(purseKey, jstate);

pursesFullState.set(
purse,
harden({
...jstate,
purse,
brand,
actions: {
async send(receiverP, valueToSend) {
// Send a value from this purse.
async send(receiverP, sendValue) {
const { amountMath } = brandTable.getByBrand(brand);
const amount = amountMath.make(valueToSend);
const amount = amountMath.make(sendValue);
const payment = await E(purse).withdraw(amount);
try {
await E(receiverP).receive(payment);
Expand Down Expand Up @@ -594,7 +599,11 @@ export async function makeWallet({
const purse = getPurse(pursePetname);
purseKeywordRecord[keyword] = purse;
const brand = purseToBrand.get(purse);
const amount = { brand, value };
const amount = {
brand,
value,
displayInfo: brandTable.getByBrand(brand).displayInfo,
};
return [keyword, amount];
},
),
Expand Down Expand Up @@ -984,8 +993,10 @@ export async function makeWallet({
} else {
purse = purseOrPetname;
}
const brandRecord = brandTable.getByBrand(brand);
paymentRecord = {
...paymentRecord,
...brandRecord,
status: 'pending',
};
updatePaymentRecord(paymentRecord);
Expand All @@ -995,6 +1006,7 @@ export async function makeWallet({
...paymentRecord,
status: 'deposited',
depositedAmount,
...brandRecord,
};
updatePaymentRecord(paymentRecord);
depositedPK.resolve(depositedAmount);
Expand Down
1 change: 1 addition & 0 deletions packages/dapp-svelte-wallet/api/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* @property {string=} depositBoardId
* @property {Petname} brandPetname
* @property {Petname} pursePetname
* @property {any} displayInfo
* @property {any} value
* @property {any} currentAmountSlots
* @property {any} currentAmount
Expand Down
6 changes: 0 additions & 6 deletions packages/dapp-svelte-wallet/api/test/test-lib-dehydrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ test('makeDehydrator', async t => {
instanceHandleMapping.addPetname('simpleExchange', handle1);
instanceHandleMapping.addPetname('atomicSwap', handle2);
instanceHandleMapping.addPetname('automaticRefund', handle3);
console.log(`ERROR EXPECTED 'already has a petname' >>>>`);
t.throws(() => instanceHandleMapping.addPetname('simpleExchange2', handle1), {
message: /val \(an object\) already has a petname/,
});
console.log(`ERROR EXPECTED 'petname simpleExchange is already in use' >>>>`);
t.throws(
() => instanceHandleMapping.addPetname('simpleExchange', harden({})),
{ message: /petname \(a string\) is already in use/ },
Expand All @@ -38,9 +36,6 @@ test('makeDehydrator', async t => {
handle1,
`renaming is successful going from val to petname`,
);
console.log(
`ERROR EXPECTED 'has not been previously named, would you like to add it instead?' >>>>`,
);
t.throws(
() => instanceHandleMapping.renamePetname('new value', harden({})),
{
Expand Down Expand Up @@ -75,7 +70,6 @@ test('makeDehydrator', async t => {
`'to be deleted' present going from val to petname`,
);
instanceHandleMapping.deletePetname('to be deleted');
console.log(`ERROR EXPECTED '"petname" not found' >>>>`);
t.throws(
() => instanceHandleMapping.petnameToVal.get('to be deleted'),
{ message: /"petname" not found/ },
Expand Down
23 changes: 22 additions & 1 deletion packages/dapp-svelte-wallet/api/test/test-lib-wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ test('lib-wallet issuer and purse methods', async t => {
{
brandBoardId: '1667979430',
depositBoardId: '604346717',
displayInfo: {
amountMathKind: 'set',
},
brandPetname: 'zoe invite',
pursePetname: 'Default Zoe invite purse',
value: [],
Expand All @@ -185,6 +188,9 @@ test('lib-wallet issuer and purse methods', async t => {
{
brandBoardId: '727995140',
brandPetname: 'moola',
displayInfo: {
amountMathKind: 'nat',
},
pursePetname: 'fun money',
value: 0,
currentAmountSlots: {
Expand Down Expand Up @@ -290,6 +296,10 @@ test('lib-wallet dapp suggests issuer, instance, installation petnames', async t
{
brandBoardId: '1667979430',
depositBoardId: '604346717',
displayInfo: {
amountMathKind: 'set',
},

brandPetname: 'zoe invite',
pursePetname: 'Default Zoe invite purse',
value: [
Expand Down Expand Up @@ -369,6 +379,9 @@ test('lib-wallet dapp suggests issuer, instance, installation petnames', async t
{
brandBoardId: '1667979430',
depositBoardId: '604346717',
displayInfo: {
amountMathKind: 'set',
},
brandPetname: 'zoe invite',
pursePetname: 'Default Zoe invite purse',
value: [
Expand Down Expand Up @@ -424,7 +437,6 @@ test('lib-wallet dapp suggests issuer, instance, installation petnames', async t
`inboxStateChangeLog with names`,
);

console.log('EXPECTED ERROR ->>> "petname" not found');
t.throws(
() => wallet.getInstallation('whatever'),
{ message: /"petname" not found/ },
Expand Down Expand Up @@ -466,6 +478,9 @@ test('lib-wallet dapp suggests issuer, instance, installation petnames', async t
{
brandBoardId: '1667979430',
depositBoardId: '604346717',
displayInfo: {
amountMathKind: 'set',
},
brandPetname: 'zoe invite',
pursePetname: 'Default Zoe invite purse',
value: [
Expand Down Expand Up @@ -632,6 +647,9 @@ test('lib-wallet offer methods', async t => {
brandBoardId: '1667979430',
depositBoardId: '604346717',
brandPetname: 'zoe invite',
displayInfo: {
amountMathKind: 'set',
},
pursePetname: 'Default Zoe invite purse',
value: [],
currentAmountSlots: {
Expand All @@ -651,6 +669,9 @@ test('lib-wallet offer methods', async t => {
{
brandBoardId: '1532665031',
brandPetname: 'moola',
displayInfo: {
amountMathKind: 'nat',
},
pursePetname: 'Fun budget',
value: 100,
currentAmountSlots: {
Expand Down
4 changes: 4 additions & 0 deletions packages/dapp-svelte-wallet/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@agoric/captp": "^1.5.2-dev.0",
"@rollup/plugin-commonjs": "^12.0.0",
"@rollup/plugin-node-resolve": "^8.0.0",
"json5": "^2.1.3",
"livereload-js": "https://github.com/agoric-labs/livereload-js",
"rollup": "^2.3.4",
"rollup-plugin-livereload": "^1.0.0",
Expand All @@ -33,5 +34,8 @@
],
"publishConfig": {
"access": "public"
},
"dependencies": {
"@rollup/plugin-replace": "^2.3.4"
}
}
4 changes: 4 additions & 0 deletions packages/dapp-svelte-wallet/ui/rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import smelte from 'smelte/rollup-plugin-smelte';
Expand Down Expand Up @@ -37,6 +38,9 @@ export default {
file: 'public/wallet/build/bundle.js'
},
plugins: [
replace({
isProduction: production,
}),
svelte({
// enable run-time checks when not in production
dev: !production,
Expand Down
11 changes: 6 additions & 5 deletions packages/dapp-svelte-wallet/ui/src/Amount.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<script>
import Petname from "./Petname.svelte";
import Debug from "../lib/Debug.svelte";
import Tooltip from "smelte/src/components/Tooltip";
import { stringifyValue } from './display';

export let amount;
export let displayInfo;

// The amount gets updated. Make this dynamic
$: ({ brand, value } = amount);
const cardinality = v => typeof v === 'number' ? v : v.length;
const stringify = v => stringifyValue(v, displayInfo);
</script>

<style>
Expand All @@ -23,7 +24,7 @@
<div slot="activator">
<b class="dotted-underline">
{value.length}
<Petname name={brand.petname} plural={value.length !== 1} />
<Petname name={brand.petname} />
</b>
</div>
{#if brand.petname === 'zoe invite'}
Expand All @@ -37,8 +38,8 @@
</Tooltip>
{:else}
<b>
{cardinality(value)}
<Petname name={brand.petname} plural={cardinality(value) !== 1} />
{stringify(value)}
<Petname name={brand.petname} />
</b>
{/if}

Expand Down
4 changes: 2 additions & 2 deletions packages/dapp-svelte-wallet/ui/src/Payment.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ import Select from "smelte/src/components/Select/Select.svelte";
<div>
{#if item.status === 'deposited'}
{#if summary}
Deposited <Amount amount={item.displayPayment.depositedAmount} />
Deposited <Amount amount={item.displayPayment.depositedAmount} displayInfo={item.displayPayment.displayInfo} />
{/if}
{:else if item.issuer}
{#if summary}
{#if !summaryLine || summaryLine === 1}
Payment amount
{/if}
{#if item.lastAmount && (!summaryLine || summaryLine === 2)}
<Amount amount={item.displayPayment.lastAmount} />
<Amount amount={item.displayPayment.lastAmount} displayInfo={item.displayPayment.displayInfo} />
{/if}
{/if}

Expand Down
Loading