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

feat!: makeOsmosisSwap() using getDenomOn #9814

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cf7f043
feat: getVBankAssetInfo() on orc.getChain('agoric')
dckc Jul 29, 2024
09928c8
chore: prune unused makeResumableAgoricNamesHack
dckc Jul 29, 2024
590dd03
chore(sendAnywhere): use agoric.getVBankAssetInfo()
dckc Jul 29, 2024
a0c3950
test: addInterchainAsset() test support
dckc Jul 31, 2024
8041ea7
chore(types): refine CosmosAssetInfo
dckc Jul 31, 2024
59dc885
chore(assets.fixture): add omniflixhub, noble
dckc Jul 31, 2024
308e6eb
feat: Orchestrator.getDenomOn (WIP)
dckc Jul 31, 2024
b046968
feat!: makeOsmosisSwap() using getDenomOn()
dckc Jul 31, 2024
9a48822
feat(LocalOrchestrationAccount): getBalance by brand
dckc Jul 31, 2024
dff557e
refactor(swapExample): factor out flows
dckc Jul 31, 2024
0890182
chore(swapExample): complete makeOsmosisSwap
dckc Jul 31, 2024
c37bcca
WIP: meeting note about PFM routing to issuing chain
dckc Aug 1, 2024
b555881
feat(ChainHub): getHoldingDenom
dckc Aug 1, 2024
66ad3c9
WIP: punt Orchestrator.getDenomOn impl
dckc Aug 1, 2024
60b30cb
WIP: remote-chain-facade getLocalDenom impl
dckc Aug 1, 2024
f7dd521
WIP: local-chain-facade: getLocalDenom impl (UNTESTED)
dckc Aug 1, 2024
46ac601
WIP: orch API: getLocalDenom (never mind getDenomOn)
dckc Aug 1, 2024
a06c29b
WIP: typeGuards: getLocalDenom
dckc Aug 1, 2024
6a213e9
WIP: makeOsmosisSwap: getDenomOn -> getLocalDenom
dckc Aug 1, 2024
7a6ba9b
fixup! WIP: makeOsmosisSwap: getDenomOn -> getLocalDenom
dckc Aug 1, 2024
f9e7f4d
WIP: remote chain facade gets chainHub too
dckc Aug 1, 2024
82e2040
WIP: always traces[0]???
dckc Aug 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions packages/orchestration/src/cosmos-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,22 @@ export type CosmosAssetInfo = {
name: string;
display: string;
symbol: string;
denom_units: Array<{ denom: Denom; exponent: number }>;
traces?: Array<{
type: 'ibc';
counterparty: {
chain_name: string;
base_denom: Denom;
channel_id: IBCChannelID;
};
chain: {
channel_id: IBCChannelID;
path: string;
};
}>;
denom_units: Array<{ denom: Denom; exponent: number; aliases?: string[] }>;
traces?: Array<
| {
type: 'ibc';
counterparty: {
chain_name: string;
base_denom: Denom;
channel_id: IBCChannelID;
};
chain: {
channel_id: IBCChannelID;
path: string;
};
}
| ({ type: 'additional-mintage' } & Record<string, unknown>)
>;
} & Record<string, unknown>;

/**
Expand Down
20 changes: 1 addition & 19 deletions packages/orchestration/src/examples/sendAnywhere.contract.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { makeStateRecord } from '@agoric/async-flow';
import { AmountShape } from '@agoric/ertp';
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { Fail } from '@endo/errors';
import { E } from '@endo/far';
import { M } from '@endo/patterns';
import { withOrchestration } from '../utils/start-helper.js';
import * as flows from './sendAnywhere.flows.js';
Expand Down Expand Up @@ -50,7 +48,7 @@ const contract = async (
zcf,
privateArgs,
zone,
{ chainHub, orchestrateAll, vowTools, zoeTools },
{ chainHub, orchestrateAll, zoeTools },
) => {
const contractState = makeStateRecord(
/** @type {{ account: OrchestrationAccount<any> | undefined }} */ {
Expand All @@ -60,27 +58,11 @@ const contract = async (

const creatorFacet = prepareChainHubAdmin(zone, chainHub);

// TODO should be a provided helper
/** @type {(brand: Brand) => Vow<VBankAssetDetail>} */
const findBrandInVBank = vowTools.retriable(
zone,
'findBrandInVBank',
/** @param {Brand} brand */
async brand => {
const { agoricNames } = privateArgs;
const assets = await E(E(agoricNames).lookup('vbankAsset')).values();
const it = assets.find(a => a.brand === brand);
it || Fail`brand ${brand} not in agoricNames.vbankAsset`;
return it;
},
);

// orchestrate uses the names on orchestrationFns to do a "prepare" of the associated behavior
const orchFns = orchestrateAll(flows, {
zcf,
contractState,
localTransfer: zoeTools.localTransfer,
findBrandInVBank,
});

const publicFacet = zone.exo(
Expand Down
12 changes: 8 additions & 4 deletions packages/orchestration/src/examples/sendAnywhere.flows.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { NonNullish } from '@agoric/internal';
import { M, mustMatch } from '@endo/patterns';

/**
* @import {GuestOf} from '@agoric/async-flow';
* @import {VBankAssetDetail} from '@agoric/vats/tools/board-utils.js';
* @import {ZoeTools} from '../utils/zoe-tools.js';
* @import {Orchestrator, LocalAccountMethods, OrchestrationAccountI, OrchestrationFlow} from '../types.js';
*/
Expand All @@ -18,13 +18,12 @@ const { entries } = Object;
* @param {object} ctx
* @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState
* @param {GuestOf<ZoeTools['localTransfer']>} ctx.localTransfer
* @param {(brand: Brand) => Promise<VBankAssetDetail>} ctx.findBrandInVBank
* @param {ZCFSeat} seat
* @param {{ chainName: string; destAddr: string }} offerArgs
*/
export async function sendIt(
orch,
{ contractState, localTransfer, findBrandInVBank },
{ contractState, localTransfer },
seat,
offerArgs,
) {
Expand All @@ -33,7 +32,12 @@ export async function sendIt(
// NOTE the proposal shape ensures that the `give` is a single asset
const { give } = seat.getProposal();
const [[_kw, amt]] = entries(give);
const { denom } = await findBrandInVBank(amt.brand);
const agoric = await orch.getChain('agoric');
const assets = await agoric.getVBankAssetInfo();
const { denom } = NonNullish(
assets.find(a => a.brand === amt.brand),
`${amt.brand} not registered in vbank`,
);
const chain = await orch.getChain(chainName);

if (!contractState.localAccount) {
Expand Down
101 changes: 33 additions & 68 deletions packages/orchestration/src/examples/swapExample.contract.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,17 @@
import { StorageNodeShape } from '@agoric/internal';
import { TimerServiceShape } from '@agoric/time';
import { M } from '@endo/patterns';
import { orcUtils } from '../utils/orc.js';
import { assertIssuerKeywords } from '@agoric/zoe/src/contractSupport/zoeHelpers.js';
import { E } from '@endo/far';
import { withOrchestration } from '../utils/start-helper.js';
import * as flows from './swapExample.flows.js';
import fetchedChainInfo from '../fetched-chain-info.js';

/**
* @import {LocalTransfer} from '../utils/zoe-tools.js';
* @import {Orchestrator, CosmosValidatorAddress, OrchestrationFlow} from '../types.js'
* @import {TimerService} from '@agoric/time';
* @import {LocalChain} from '@agoric/vats/src/localchain.js';
* @import {Remote} from '@agoric/internal';
* @import {CosmosInterchainService} from '../exos/cosmos-interchain-service.js';
* @import {NameHub} from '@agoric/vats';
* @import {Zone} from '@agoric/zone';
* @import {OrchestrationTools} from '../utils/start-helper.js';
*/

/**
* @satisfies {OrchestrationFlow}
* @param {Orchestrator} orch
* @param {object} ctx
* @param {LocalTransfer} ctx.localTransfer
* @param {ZCFSeat} seat
* @param {object} offerArgs
* @param {Amount<'nat'>} offerArgs.staked
* @param {CosmosValidatorAddress} offerArgs.validator
*/
const stakeAndSwapFn = async (orch, { localTransfer }, seat, offerArgs) => {
const { give } = seat.getProposal();

const omni = await orch.getChain('omniflixhub');
const agoric = await orch.getChain('agoric');

const [omniAccount, localAccount] = await Promise.all([
omni.makeAccount(),
agoric.makeAccount(),
]);

const omniAddress = omniAccount.getAddress();

// deposit funds from user seat to LocalChainAccount
await localTransfer(seat, localAccount, give);
seat.exit();

// build swap instructions with orcUtils library
const transferMsg = orcUtils.makeOsmosisSwap({
destChain: 'omniflixhub',
destAddress: omniAddress,
amountIn: give.Stable,
brandOut: /** @type {any} */ ('FIXME'),
slippage: 0.03,
});

try {
await localAccount.transferSteps(give.Stable, transferMsg);
await omniAccount.delegate(offerArgs.validator, offerArgs.staked);
} catch (e) {
console.error(e);
}
};

/** @type {ContractMeta<typeof start>} */
export const meta = {
privateArgsShape: {
Expand All @@ -86,32 +38,45 @@ export const makeNatAmountShape = (brand, min) =>
/**
* Orchestration contract to be wrapped by withOrchestration for Zoe
*
* @param {ZCF} zcf
* @param {{
* agoricNames: Remote<NameHub>;
* localchain: Remote<LocalChain>;
* orchestrationService: Remote<CosmosInterchainService>;
* storageNode: Remote<StorageNode>;
* timerService: Remote<TimerService>;
* @param {ZCF<{ baseDenom: string; baseName: string }>} zcf
* @param {import('../utils/start-helper.js').OrchestrationPowers & {
* marshaller: Marshaller;
* }} privateArgs
* @param {Zone} zone
* @param {OrchestrationTools} tools
*/
const contract = async (zcf, privateArgs, zone, { orchestrate, zoeTools }) => {
const { brands } = zcf.getTerms();
const contract = async (
zcf,
privateArgs,
zone,
{ zoeTools, orchestrateAll, chainHub },
) => {
assertIssuerKeywords(zcf, ['Stable', 'Out']);
const { brands, baseDenom, baseName } = zcf.getTerms();

/** deprecated historical example */
const swapAndStakeHandler = orchestrate(
'LSTTia',
{ zcf, localTransfer: zoeTools.localTransfer },
stakeAndSwapFn,
);
const handlers = orchestrateAll(flows, {
zcf,
localTransfer: zoeTools.localTransfer,
brandOut: brands.Out,
});

const assets = await E(
E(privateArgs.agoricNames).lookup('vbankAsset'),
).values();
const info = assets.find(a => a.brand === brands.Out);
for (const chainName of ['agoric', 'omniflixhub']) {
chainHub.registerChain(chainName, fetchedChainInfo[chainName]);
}
chainHub.registerAsset(info.denom, {
baseDenom,
baseName,
chainName: 'agoric',
});

const publicFacet = zone.exo('publicFacet', undefined, {
makeSwapAndStakeInvitation() {
return zcf.makeInvitation(
swapAndStakeHandler,
handlers.swapAndStake,
'Swap for TIA and stake',
undefined,
harden({
Expand Down
58 changes: 58 additions & 0 deletions packages/orchestration/src/examples/swapExample.flows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { orcUtils } from '../utils/orc.js';

/**
* @import {LocalTransfer} from '../utils/zoe-tools.js';
* @import {Orchestrator, CosmosValidatorAddress, OrchestrationFlow} from '../types.js'
*/
/**
* @satisfies {OrchestrationFlow}
* @param {Orchestrator} orch
* @param {object} ctx
* @param {LocalTransfer} ctx.localTransfer
* @param {Brand} ctx.brandOut
* @param {ZCFSeat} seat
* @param {object} offerArgs
* @param {Amount<'nat'>} offerArgs.staked
* @param {CosmosValidatorAddress} offerArgs.validator
*/
export const swapAndStake = async (
orch,
{ localTransfer, brandOut },
seat,
offerArgs,
) => {
const { give } = seat.getProposal();

const omni = await orch.getChain('omniflixhub');
const agoric = await orch.getChain('agoric');

const [omniAccount, localAccount] = await Promise.all([
omni.makeAccount(),
agoric.makeAccount(),
]);

const omniAddress = omniAccount.getAddress();

// deposit funds from user seat to LocalChainAccount
await localTransfer(seat, localAccount, give);
seat.exit();

// build swap instructions with orcUtils library
const transferMsg = await orcUtils.makeOsmosisSwap(
{
destChain: 'omniflixhub',
destAddress: omniAddress,
amountIn: give.Stable,
brandOut,
slippage: 0.03,
},
orch,
);

try {
await localAccount.transferSteps(give.Stable, transferMsg);
await omniAccount.delegate(offerArgs.validator, offerArgs.staked);
} catch (e) {
console.error(e);
}
};
Loading
Loading