-
Notifications
You must be signed in to change notification settings - Fork 208
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(localchain): add transfer
method to LocalChainAccountKit holder
#9380
Changes from all commits
142c408
0f8eedb
9c23e49
fd11145
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,14 @@ import type { | |
LocalIbcAddress, | ||
RemoteIbcAddress, | ||
} from '@agoric/vats/tools/ibc-utils.js'; | ||
import { MsgTransfer } from '@agoric/cosmic-proto/ibc/applications/transfer/v1/tx.js'; | ||
import type { State as IBCConnectionState } from '@agoric/cosmic-proto/ibc/core/connection/v1/connection.js'; | ||
import type { | ||
Order, | ||
State as IBCChannelState, | ||
} from '@agoric/cosmic-proto/ibc/core/channel/v1/channel.js'; | ||
import { IBCChannelID, IBCConnectionID } from '@agoric/vats'; | ||
import { MapStore } from '@agoric/store'; | ||
import type { AmountArg, ChainAddress, DenomAmount } from './types.js'; | ||
|
||
/** A helper type for type extensions. */ | ||
|
@@ -29,25 +37,37 @@ export type CosmosValidatorAddress = ChainAddress & { | |
addressEncoding: 'bech32'; | ||
}; | ||
|
||
/** Represents an IBC Connection between two chains, which can contain multiple Channels. */ | ||
export type IBCConnectionInfo = { | ||
id: IBCConnectionID; // e.g. connection-0 | ||
client_id: string; // '07-tendermint-0' | ||
state: IBCConnectionState; | ||
counterparty: { | ||
client_id: string; | ||
connection_id: IBCConnectionID; | ||
prefix: { | ||
key_prefix: string; | ||
}; | ||
}; | ||
versions: { identifier: string; features: string[] }[]; | ||
delay_period: bigint; | ||
transferChannel: { | ||
portId: string; | ||
channelId: IBCChannelID; | ||
counterPartyPortId: string; | ||
counterPartyChannelId: IBCChannelID; | ||
ordering: Order; | ||
state: IBCChannelState; | ||
version: string; // e.eg. 'ics20-1' | ||
}; | ||
}; | ||
|
||
/** | ||
* Info for a Cosmos-based chain. | ||
*/ | ||
export type CosmosChainInfo = { | ||
chainId: string; | ||
ibcConnectionInfo: { | ||
id: string; // e.g. connection-0 | ||
client_id: string; // '07-tendermint-0' | ||
state: 'OPEN' | 'TRYOPEN' | 'INIT' | 'CLOSED'; | ||
counterparty: { | ||
client_id: string; | ||
connection_id: string; | ||
prefix: { | ||
key_prefix: string; | ||
}; | ||
}; | ||
versions: { identifier: string; features: string[] }[]; | ||
delay_period: bigint; | ||
}; | ||
connections: MapStore<string, IBCConnectionInfo>; // chainId or wellKnownName | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mutable... hm... 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would you expect to see instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure... it's an adjustment to my mental model, and I'm not sure where I might have assumed that ChainInfo is immutable. I just need to be aware of it going forward, I suppose. (technically, this still is immutable; the value of the One impact is the contents of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when do we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question, I am also wondering the same. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think solving this can wait for #9063 |
||
icaEnabled: boolean; | ||
icqEnabled: boolean; | ||
pfmEnabled: boolean; | ||
|
@@ -197,3 +217,9 @@ export interface IcaAccount { | |
export type LiquidStakingMethods = { | ||
liquidStake: (amount: AmountArg) => Promise<void>; | ||
}; | ||
|
||
export type IBCMsgTransferOptions = { | ||
timeoutHeight?: MsgTransfer['timeoutHeight']; | ||
timeoutTimestamp?: MsgTransfer['timeoutTimestamp']; | ||
memo?: string; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,20 @@ | ||
/** | ||
* @file Stake BLD contract | ||
* | ||
*/ | ||
|
||
import { makeTracer } from '@agoric/internal'; | ||
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js'; | ||
import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js'; | ||
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js'; | ||
import { makeDurableZone } from '@agoric/zone/durable.js'; | ||
import { M } from '@endo/patterns'; | ||
import { E } from '@endo/far'; | ||
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js'; | ||
import { atomicTransfer } from '@agoric/zoe/src/contractSupport/atomicTransfer.js'; | ||
import { prepareLocalchainAccountKit } from '../exos/localchainAccountKit.js'; | ||
import { deeplyFulfilled } from '@endo/marshal'; | ||
import { M } from '@endo/patterns'; | ||
import { prepareLocalChainAccountKit } from '../exos/local-chain-account-kit.js'; | ||
import { prepareMockChainInfo } from '../utils/mockChainInfo.js'; | ||
|
||
/** | ||
* @import {TimerBrand, TimerService} from '@agoric/time'; | ||
*/ | ||
|
||
const trace = makeTracer('StakeBld'); | ||
|
||
|
@@ -20,12 +25,15 @@ const trace = makeTracer('StakeBld'); | |
* localchain: import('@agoric/vats/src/localchain.js').LocalChain; | ||
* marshaller: Marshaller; | ||
* storageNode: StorageNode; | ||
* timerService: TimerService; | ||
* timerBrand: TimerBrand; | ||
* }} privateArgs | ||
* @param {import("@agoric/vat-data").Baggage} baggage | ||
*/ | ||
export const start = async (zcf, privateArgs, baggage) => { | ||
const { BLD } = zcf.getTerms().brands; | ||
const BLD = zcf.getTerms().brands.In; | ||
|
||
// XXX is this safe to call before prepare statements are completed? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nope, it's a remote call and those can't happen in the first crank of upgrade. but we can tackle that when this gets an upgrade test |
||
const bldAmountShape = await E(BLD).getAmountShape(); | ||
|
||
const zone = makeDurableZone(baggage); | ||
|
@@ -34,48 +42,81 @@ export const start = async (zcf, privateArgs, baggage) => { | |
baggage, | ||
privateArgs.marshaller, | ||
); | ||
const makeLocalchainAccountKit = prepareLocalchainAccountKit( | ||
|
||
// Mocked until #8879 | ||
// Would expect this to be instantiated elsewhere, and passed in as a reference | ||
const agoricChainInfo = prepareMockChainInfo(zone); | ||
|
||
const makeLocalChainAccountKit = prepareLocalChainAccountKit( | ||
baggage, | ||
makeRecorderKit, | ||
zcf, | ||
privateArgs.timerService, | ||
privateArgs.timerBrand, | ||
agoricChainInfo, | ||
); | ||
|
||
const publicFacet = zone.exo('StakeBld', undefined, { | ||
makeStakeBldInvitation() { | ||
return zcf.makeInvitation( | ||
async seat => { | ||
const { give } = seat.getProposal(); | ||
trace('makeStakeBldInvitation', give); | ||
// XXX type appears local but it's remote | ||
const account = await E(privateArgs.localchain).makeAccount(); | ||
const lcaSeatKit = zcf.makeEmptySeatKit(); | ||
atomicTransfer(zcf, seat, lcaSeatKit.zcfSeat, give); | ||
seat.exit(); | ||
trace('makeStakeBldInvitation tryExit lca userSeat'); | ||
await E(lcaSeatKit.userSeat).tryExit(); | ||
trace('awaiting payouts'); | ||
const payouts = await E(lcaSeatKit.userSeat).getPayouts(); | ||
const { holder, invitationMakers } = makeLocalchainAccountKit( | ||
account, | ||
privateArgs.storageNode, | ||
); | ||
trace('awaiting deposit'); | ||
await E(account).deposit(await payouts.In); | ||
async function makeLocalAccountKit() { | ||
const account = await E(privateArgs.localchain).makeAccount(); | ||
const address = await E(account).getAddress(); | ||
return makeLocalChainAccountKit({ | ||
account, | ||
address, | ||
storageNode: privateArgs.storageNode, | ||
}); | ||
} | ||
|
||
return { | ||
const publicFacet = zone.exo( | ||
'StakeBld', | ||
M.interface('StakeBldI', { | ||
makeAccount: M.callWhen().returns(M.remotable('LocalChainAccountHolder')), | ||
makeAcountInvitationMaker: M.callWhen().returns(InvitationShape), | ||
makeStakeBldInvitation: M.callWhen().returns(InvitationShape), | ||
}), | ||
{ | ||
makeStakeBldInvitation() { | ||
return zcf.makeInvitation( | ||
async seat => { | ||
const { give } = seat.getProposal(); | ||
trace('makeStakeBldInvitation', give); | ||
const { holder, invitationMakers } = await makeLocalAccountKit(); | ||
const { In } = await deeplyFulfilled( | ||
withdrawFromSeat(zcf, seat, give), | ||
); | ||
await E(holder).deposit(In); | ||
seat.exit(); | ||
return harden({ | ||
publicSubscribers: holder.getPublicTopics(), | ||
invitationMakers, | ||
account: holder, | ||
}); | ||
}, | ||
'wantStake', | ||
undefined, | ||
M.splitRecord({ | ||
give: { In: bldAmountShape }, | ||
}), | ||
); | ||
}, | ||
async makeAccount() { | ||
trace('makeAccount'); | ||
const { holder } = await makeLocalAccountKit(); | ||
return holder; | ||
}, | ||
makeAcountInvitationMaker() { | ||
trace('makeCreateAccountInvitation'); | ||
return zcf.makeInvitation(async seat => { | ||
seat.exit(); | ||
const { holder, invitationMakers } = await makeLocalAccountKit(); | ||
return harden({ | ||
publicSubscribers: holder.getPublicTopics(), | ||
invitationMakers, | ||
account: holder, | ||
}; | ||
}, | ||
'wantStake', | ||
undefined, | ||
M.splitRecord({ | ||
give: { In: bldAmountShape }, | ||
}), | ||
); | ||
}); | ||
}, 'wantLocalChainAccount'); | ||
}, | ||
}, | ||
}); | ||
); | ||
|
||
return { publicFacet }; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typed return values for
LocalChainAccount['executeTx']
. Here's a corresponding test:https://github.com/Agoric/agoric-sdk/pull/9351/files#diff-5029634754ca0f3ec74d84e0f67e99fe74eaf5007b291a7ba337e04e64c8f9c7