Skip to content

Commit

Permalink
chore: use address-hook encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpatrickdev committed Dec 13, 2024
1 parent e86a5e1 commit 6091992
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 212 deletions.
1 change: 1 addition & 0 deletions packages/fast-usdc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
},
"dependencies": {
"@agoric/client-utils": "^0.1.0",
"@agoric/cosmic-proto": "^0.4.0",
"@agoric/ertp": "^0.16.2",
"@agoric/internal": "^0.3.2",
"@agoric/notifier": "^0.6.2",
Expand Down
13 changes: 7 additions & 6 deletions packages/fast-usdc/src/cli/transfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
makeVStorage,
pickEndpoint,
} from '@agoric/client-utils';
import { encodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
import { queryFastUSDCLocalChainAccount } from '../util/agoric.js';
import { depositForBurn, makeProvider } from '../util/cctp.js';
import {
Expand All @@ -22,7 +23,7 @@ import {
const transfer = async (
/** @type {File} */ configFile,
/** @type {string} */ amount,
/** @type {string} */ destination,
/** @type {string} */ EUD,
out = console,
fetch = globalThis.fetch,
/** @type {VStorage | undefined} */ vstorage,
Expand All @@ -39,13 +40,13 @@ const transfer = async (
{ chainName: 'agoric', rpcAddrs: [pickEndpoint(netConfig)] },
);
const agoricAddr = await queryFastUSDCLocalChainAccount(vstorage, out);
const appendedAddr = `${agoricAddr}?EUD=${destination}`;
out.log(`forwarding destination ${appendedAddr}`);
const encodedAddr = encodeAddressHook(agoricAddr, { EUD });
out.log(`forwarding destination ${encodedAddr}`);

const { exists, address } = await queryForwardingAccount(
config.nobleApi,
config.nobleToAgoricChannel,
appendedAddr,
encodedAddr,
out,
fetch,
);
Expand All @@ -58,13 +59,13 @@ const transfer = async (
signer,
signerAddress,
config.nobleToAgoricChannel,
appendedAddr,
encodedAddr,
out,
);
out.log(res);
} catch (e) {
out.error(
`Error registering noble forwarding account for ${appendedAddr} on channel ${config.nobleToAgoricChannel}`,
`Error registering noble forwarding account for ${encodedAddr} on channel ${config.nobleToAgoricChannel}`,
);
throw e;
}
Expand Down
16 changes: 7 additions & 9 deletions packages/fast-usdc/src/exos/advancer.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { decodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
import { AmountMath } from '@agoric/ertp';
import { assertAllDefined, makeTracer } from '@agoric/internal';
import { AnyNatAmountShape, ChainAddressShape } from '@agoric/orchestration';
import { pickFacet } from '@agoric/vat-data';
import { VowShape } from '@agoric/vow';
import { E } from '@endo/far';
import { M } from '@endo/patterns';
import { M, mustMatch } from '@endo/patterns';
import {
CctpTxEvidenceShape,
EudParamShape,
AddressHookShape,
EvmHashShape,
} from '../type-guards.js';
import { addressTools } from '../utils/address.js';
import { makeFeeTools } from '../utils/fees.js';

/**
Expand All @@ -21,7 +21,7 @@ import { makeFeeTools } from '../utils/fees.js';
* @import {ZoeTools} from '@agoric/orchestration/src/utils/zoe-tools.js';
* @import {VowTools} from '@agoric/vow';
* @import {Zone} from '@agoric/zone';
* @import {CctpTxEvidence, EvmHash, FeeConfig, LogFn, NobleAddress} from '../types.js';
* @import {CctpTxEvidence, AddressHook, EvmHash, FeeConfig, LogFn, NobleAddress} from '../types.js';
* @import {StatusManager} from './status-manager.js';
* @import {LiquidityPoolKit} from './liquidity-pool.js';
*/
Expand Down Expand Up @@ -147,11 +147,9 @@ export const prepareAdvancerKit = (

const { borrowerFacet, poolAccount } = this.state;
const { recipientAddress } = evidence.aux;
// throws if EUD is not found
const { EUD } = addressTools.getQueryParams(
recipientAddress,
EudParamShape,
);
const decoded = decodeAddressHook(recipientAddress);
mustMatch(decoded, AddressHookShape);
const { EUD } = /** @type {AddressHook['query']} */ (decoded.query);
log(`decoded EUD: ${EUD}`);
// throws if the bech32 prefix is not found
const destination = chainHub.makeChainAddress(EUD);
Expand Down
23 changes: 14 additions & 9 deletions packages/fast-usdc/src/exos/settler.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { atob } from '@endo/base64';
import { E } from '@endo/far';
import { M } from '@endo/patterns';

import { decodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
import { PendingTxStatus } from '../constants.js';
import { addressTools } from '../utils/address.js';
import { makeFeeTools } from '../utils/fees.js';
import { EvmHashShape } from '../type-guards.js';

Expand Down Expand Up @@ -151,14 +151,19 @@ export const prepareSettler = (
return;
}

if (!addressTools.hasQueryParams(tx.receiver)) {
console.log('not query params', tx.receiver);
return;
}

const { EUD } = addressTools.getQueryParams(tx.receiver);
if (!EUD) {
console.log('no EUD parameter', tx.receiver);
let EUD;
try {
({ EUD } = decodeAddressHook(tx.receiver).query);
if (!EUD) {
log('no EUD parameter', tx.receiver);
return;
}
if (typeof EUD !== 'string') {
log('EUD is not a string', EUD);
return;
}
} catch (e) {
log('no query params', tx.receiver);
return;
}

Expand Down
10 changes: 6 additions & 4 deletions packages/fast-usdc/src/type-guards.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { PendingTxStatus } from './constants.js';
* @import {TypedPattern} from '@agoric/internal';
* @import {FastUsdcTerms} from './fast-usdc.contract.js';
* @import {USDCProposalShapes} from './pool-share-math.js';
* @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy} from './types.js';
* @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy, AddressHook} from './types.js';
*/

/**
Expand Down Expand Up @@ -67,10 +67,12 @@ export const PendingTxShape = {
};
harden(PendingTxShape);

export const EudParamShape = {
EUD: M.string(),
/** @type {TypedPattern<AddressHook>} */
export const AddressHookShape = {
baseAddress: M.string(),
query: { EUD: M.string() },
};
harden(EudParamShape);
harden(AddressHookShape);

const NatAmountShape = { brand: BrandShape, value: M.nat() };
/** @type {TypedPattern<FeeConfig>} */
Expand Down
9 changes: 9 additions & 0 deletions packages/fast-usdc/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,14 @@ export type FastUSDCConfig = {
assetInfo: [Denom, DenomDetail & { brandKey?: string }][];
} & CopyRecord;

/** decoded address hook parameters */
export type AddressHook = {
baseAddress: string;
query: {
/** end user destination address */
EUD: string;
};
};

export type * from './constants.js';
export type { LiquidityPoolKit } from './exos/liquidity-pool.js';
71 changes: 0 additions & 71 deletions packages/fast-usdc/src/utils/address.js

This file was deleted.

2 changes: 1 addition & 1 deletion packages/fast-usdc/test/cli/snapshots/transfer.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Generated by [AVA](https://avajs.dev).
typeUrl: '/noble.forwarding.v1.MsgRegisterAccount',
value: {
channel: 'channel-test-7',
recipient: 'agoric123456?EUD=dydx1234',
recipient: 'agoric10rchp4vc53apxn32q42c3zryml8xq3xshyzuhjk6405wtxy7tl3d7e0f8az423pav3ukg7p3xgengqpq4066gy',
signer: 'noble09876',
},
},
Expand Down
Binary file modified packages/fast-usdc/test/cli/snapshots/transfer.test.ts.snap
Binary file not shown.
25 changes: 17 additions & 8 deletions packages/fast-usdc/test/cli/transfer.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import test from 'ava';
import { encodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
import transfer from '../../src/cli/transfer.js';
import {
mockOut,
Expand Down Expand Up @@ -63,14 +64,18 @@ test('Transfer registers the noble forwarding account if it does not exist', asy
};
const out = mockOut();
const file = mockFile(path, JSON.stringify(config));
const agoricSettlementAccount = 'agoric123456';
const agoricSettlementAccount =
'agoric16kv2g7snfc4q24vg3pjdlnnqgngtjpwtetd2h689nz09lcklvh5s8u37ek';
const settlementAccountVstoragePath = 'published.fastUsdc.settlementAccount';
const vstorageMock = makeVstorageMock({
[settlementAccountVstoragePath]: agoricSettlementAccount,
});
const amount = '150';
const destination = 'dydx1234';
const nobleFwdAccountQuery = `${nobleApi}/noble/forwarding/v1/address/${nobleToAgoricChannel}/${agoricSettlementAccount}${encodeURIComponent('?EUD=')}${destination}/`;
const EUD = 'dydx1234';
const nobleFwdAccountQuery = `${nobleApi}/noble/forwarding/v1/address/${nobleToAgoricChannel}/${encodeAddressHook(
agoricSettlementAccount,
{ EUD },
)}/`;
const fetchMock = makeFetchMock({
[nobleFwdAccountQuery]: {
address: 'noble14lwerrcfzkzrv626w49pkzgna4dtga8c5x479h',
Expand All @@ -84,7 +89,7 @@ test('Transfer registers the noble forwarding account if it does not exist', asy
await transfer.transfer(
file,
amount,
destination,
EUD,
// @ts-expect-error mocking console
out,
fetchMock.fetch,
Expand Down Expand Up @@ -114,14 +119,18 @@ test('Transfer signs and broadcasts the depositForBurn message on Ethereum', asy
};
const out = mockOut();
const file = mockFile(path, JSON.stringify(config));
const agoricSettlementAccount = 'agoric123456';
const agoricSettlementAccount =
'agoric16kv2g7snfc4q24vg3pjdlnnqgngtjpwtetd2h689nz09lcklvh5s8u37ek';
const settlementAccountVstoragePath = 'published.fastUsdc.settlementAccount';
const vstorageMock = makeVstorageMock({
[settlementAccountVstoragePath]: agoricSettlementAccount,
});
const amount = '150';
const destination = 'dydx1234';
const nobleFwdAccountQuery = `${nobleApi}/noble/forwarding/v1/address/${nobleToAgoricChannel}/${agoricSettlementAccount}${encodeURIComponent('?EUD=')}${destination}/`;
const EUD = 'dydx1234';
const nobleFwdAccountQuery = `${nobleApi}/noble/forwarding/v1/address/${nobleToAgoricChannel}/${encodeAddressHook(
agoricSettlementAccount,
{ EUD },
)}/`;
const fetchMock = makeFetchMock({
[nobleFwdAccountQuery]: {
address: 'noble14lwerrcfzkzrv626w49pkzgna4dtga8c5x479h',
Expand All @@ -135,7 +144,7 @@ test('Transfer signs and broadcasts the depositForBurn message on Ethereum', asy
await transfer.transfer(
file,
amount,
destination,
EUD,
// @ts-expect-error mocking console
out,
fetchMock.fetch,
Expand Down
34 changes: 27 additions & 7 deletions packages/fast-usdc/test/exos/advancer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import fetchedChainInfo from '@agoric/orchestration/src/fetched-chain-info.js';
import { Far } from '@endo/pass-style';
import type { NatAmount } from '@agoric/ertp';
import { type ZoeTools } from '@agoric/orchestration/src/utils/zoe-tools.js';
import { Fail, q } from '@endo/errors';
import { q } from '@endo/errors';
import {
decodeAddressHook,
encodeAddressHook,
} from '@agoric/cosmic-proto/address-hooks.js';
import { PendingTxStatus } from '../../src/constants.js';
import { prepareAdvancer } from '../../src/exos/advancer.js';
import type { SettlerKit } from '../../src/exos/settler.js';
import { prepareStatusManager } from '../../src/exos/status-manager.js';
import { makeFeeTools } from '../../src/utils/fees.js';
import { addressTools } from '../../src/utils/address.js';
import { commonSetup } from '../supports.js';
import { MockCctpTxEvidences, intermediateRecipient } from '../fixtures.js';
import {
Expand Down Expand Up @@ -215,8 +218,7 @@ test('updates status to ADVANCING in happy path', async t => {
forwardingAddress: mockEvidence.tx.forwardingAddress,
fullAmount: usdc.make(mockEvidence.tx.amount),
destination: {
value: addressTools.getQueryParams(mockEvidence.aux.recipientAddress)
.EUD,
value: decodeAddressHook(mockEvidence.aux.recipientAddress).query.EUD,
},
},
true, // indicates transfer succeeded
Expand Down Expand Up @@ -344,8 +346,7 @@ test('calls notifyAdvancingResult (AdvancedFailed) on failed transfer', async t
usdc.make(mockEvidence.tx.amount),
),
destination: {
value: addressTools.getQueryParams(mockEvidence.aux.recipientAddress)
.EUD,
value: decodeAddressHook(mockEvidence.aux.recipientAddress).query.EUD,
},
},
false, // this indicates transfer failed
Expand Down Expand Up @@ -373,10 +374,29 @@ test('updates status to OBSERVED if pre-condition checks fail', async t => {
);

t.deepEqual(inspectLogs(), [
[
'Advancer error:',
Error('query: {} - Must have missing properties ["EUD"]'),
],
]);

await advancer.handleTransactionEvent({
...MockCctpTxEvidences.AGORIC_NO_PARAMS(
encodeAddressHook(
'agoric16kv2g7snfc4q24vg3pjdlnnqgngtjpwtetd2h689nz09lcklvh5s8u37ek',
{ EUD: 'osmo1234', extra: 'value' },
),
),
txHash:
'0xc81bc6105b60a234c7c50ac17816ebcd5561d366df8bf3be59ff387552761799',
});

const [, ...remainingLogs] = inspectLogs();
t.deepEqual(remainingLogs, [
[
'Advancer error:',
Error(
'Unable to parse query params: "agoric16kv2g7snfc4q24vg3pjdlnnqgngtjpwtetd2h689nz09lcklvh5s8u37ek"',
'query: {"EUD":"osmo1234","extra":"value"} - Must not have unexpected properties: ["extra"]',
),
],
]);
Expand Down
Loading

0 comments on commit 6091992

Please sign in to comment.