Skip to content

Commit

Permalink
wip 12
Browse files Browse the repository at this point in the history
  • Loading branch information
egasimus committed Oct 28, 2023
1 parent 726c9df commit f50f779
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 153 deletions.
19 changes: 10 additions & 9 deletions agent/agent-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,22 +318,23 @@ class AgentConsole extends Console {
const len = Math.max(40, Object.keys(contracts).reduce((x,r)=>Math.max(x,r.length),0))
const count = Object.values(contracts).length
if (count <= 0) return this.info(`${name} is an empty deployment`)
this.info(`${bold(String(count))} contract(s) in deployment ${bold(name)}:`)
this.br()
this.info()
this.info(`${bold(String(count))} unit(s) in deployment ${bold(name)}:`)
for (const name of Object.keys(contracts).sort()) {
this.info()
this.receipt(name, contracts[name], len)
this.br()
}
this.info()
return this
}
receipt (name: string, receipt?: any, len?: number) {
let { address, codeHash, codeId, crate, repository } = receipt || {}
this.info(`name: ${bold(name || gray('(no name)')) }`)
this.info(`addr: ${bold(address || gray('(no address)')) }`)
this.info(`hash: ${bold(codeHash || gray('(no code hash)'))}`)
this.info(`code: ${bold(codeId) || gray('(no code id)') }`)
this.info(`repo: ${bold(repository || gray('(no repo)')) }`)
this.info(`crate: ${bold(crate || gray('(no crate)')) }`)
this.info(` ${bold(name || gray('(no name)')) }`)
this.info(` addr: ${bold(address || gray('(no address)')) }`)
this.info(` hash: ${bold(codeHash || gray('(no code hash)'))}`)
this.info(` code: ${bold(codeId) || gray('(no code id)') }`)
this.info(` repo: ${bold(repository || gray('(no repo)')) }`)
this.info(` crate: ${bold(crate || gray('(no crate)')) }`)
return this
}
}
Expand Down
39 changes: 26 additions & 13 deletions agent/agent-batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Error, Console, into } from './agent-base'
import type {
Class, Message, CodeId, Address, Name, Into, ICoin, Many, CodeHash
} from './agent-base'
import type { Agent, ExecOpts } from './agent-chain'
import type { Agent } from './agent-chain'
import { ContractInstance } from './agent-contract'

/** A constructor for a Batch subclass. */
Expand Down Expand Up @@ -58,18 +58,19 @@ export abstract class Batch implements BatchAgent {
}

/** Either submit or save the batch. */
async run (opts: ExecOpts|string = "", save: boolean = false): Promise<any> {
this.log(save ? 'Saving' : 'Submitting')
if (typeof opts === 'string') opts = { memo: opts }
const { memo = '' } = opts ?? {}
async run (options: Partial<{
memo: string,
save: boolean
}> = {}): Promise<unknown> {
this.log(options.save ? 'Saving' : 'Submitting')
if (this.depth > 0) {
this.log.warn('Unnesting batch. Depth:', --this.depth)
this.depth--
return null as any // result ignored
} else if (save) {
return this.save(memo)
} else if (options.save) {
return this.save(options.memo)
} else {
return this.submit(memo)
return this.submit(options.memo)
}
}

Expand Down Expand Up @@ -183,8 +184,8 @@ export abstract class Batch implements BatchAgent {
/** Add an exec message to the batch. */
async execute (
contract: Address|{ address: Address, codeHash?: CodeHash },
msg: Message,
{ send }: ExecOpts = {}
message: Message,
options: Parameters<Agent["execute"]>[2] = {}
): Promise<this> {
let address: Address
let codeHash: CodeHash|undefined = undefined
Expand All @@ -194,7 +195,15 @@ export abstract class Batch implements BatchAgent {
address = contract.address
codeHash = contract.codeHash
}
this.add({ exec: { sender: this.address, contract: address, codeHash, msg, funds: send } })
this.add({
exec: {
sender: this.address,
contract: address,
codeHash,
msg: message,
funds: options.execSend
}
})
return this
}
/** Queries are disallowed in the middle of a batch because
Expand Down Expand Up @@ -255,11 +264,15 @@ export abstract class Batch implements BatchAgent {
throw new Error.Invalid.Batching("query balance")
}
/** Disallowed in batch - do it beforehand or afterwards. */
async send (to: Address, amounts: ICoin[], opts?: ExecOpts): Promise<void|unknown> {
async send (
recipient: Address, amounts: ICoin[], options?: Parameters<Agent["send"]>[2]
): Promise<void|unknown> {
throw new Error.Invalid.Batching("send")
}
/** Disallowed in batch - do it beforehand or afterwards. */
async sendMany (outputs: [Address, ICoin[]][], opts?: ExecOpts): Promise<void|unknown> {
async sendMany (
outputs: [Address, ICoin[]][], options?: Parameters<Agent["sendMany"]>[1]
): Promise<void|unknown> {
throw new Error.Invalid.Batching("send")
}
/** Nested batches are "flattened": trying to create a batch
Expand Down
61 changes: 25 additions & 36 deletions agent/agent-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,41 +341,39 @@ export interface AgentClass<A extends Agent> extends Class<A, ConstructorParamet
/** By authenticating to a network you obtain an Agent,
* which can perform transactions as the authenticated identity. */
export abstract class Agent {

/** Logger. */
log = new Console(this.constructor.name)

/** The friendly name of the agent. */
name?: string

/** The chain on which this agent operates. */
chain?: Chain

/** The address from which transactions are signed and sent. */
address?: Address

/** The wallet's mnemonic. */
mnemonic?: string

/** Default fee maximums for send, upload, init, and execute. */
fees?: AgentFees

/** The Batch subclass to use. */
Batch: BatchClass<Batch> = (this.constructor as AgentClass<typeof this>).Batch

/** The default Batch class used by this Agent. */
static Batch: BatchClass<Batch> // populated below

constructor (options: Partial<Agent> = {}) {
this.chain = options.chain ?? this.chain
this.name = options.name ?? this.name
this.fees = options.fees ?? this.fees
this.address = options.address ?? this.address
this.name = options.name ?? this.name
this.fees = options.fees ?? this.fees
this.address = options.address ?? this.address
hideProperties(this, 'chain', 'address', 'log', 'Batch')
}

get [Symbol.toStringTag]() {
return `${this.address} @ ${this.chain?.id}${this.mnemonic ? ' (*)' : ''}`
return `${this.address} @ ${this.chain?.id}`
}

/** The wallet's mnemonic (write-only). */
get mnemonic (): Promise<string> {
throw new Error('mnemonic is write-only')
}

set mnemonic (mnemonic: string) {
}

/** Complete the asynchronous initialization of this Agent. */
Expand Down Expand Up @@ -443,10 +441,10 @@ export abstract class Agent {
}

/** Send native tokens to 1 recipient. */
abstract send (to: Address, amounts: ICoin[], opts?: ExecOpts): Promise<void|unknown>
abstract send (to: Address, amounts: ICoin[], opts?: unknown): Promise<void|unknown>

/** Send native tokens to multiple recipients. */
abstract sendMany (outputs: [Address, ICoin[]][], opts?: ExecOpts): Promise<void|unknown>
abstract sendMany (outputs: [Address, ICoin[]][], opts?: unknown): Promise<void|unknown>

/** Upload a contract's code, generating a new code id/hash pair. */
async upload (
Expand Down Expand Up @@ -500,14 +498,15 @@ export abstract class Agent {

/** Upload multiple contracts. */
async uploadMany (
codes: Many<string|URL|Uint8Array|Partial<ContractUpload>>,
codes: Many<string|URL|Uint8Array|Partial<CompiledCode>>,
options: Parameters<typeof this["upload"]>[1]
) {
return mapAsync(codes, code => this.upload(code, options))
}

protected abstract doUpload (
data: Uint8Array, options: Parameters<typeof this["upload"]>[1]
data: Uint8Array,
options: Parameters<typeof this["upload"]>[1]
): Promise<Partial<ContractUpload>>

/** Create a new smart contract from a code id, label and init message.
Expand All @@ -531,7 +530,6 @@ export abstract class Agent {
if (!contract.codeId) {
throw new Error.Missing.CodeId()
}
console.log({contract, options}, !!options.label)
if (!options.label) {
throw new Error.Missing.Label()
}
Expand Down Expand Up @@ -623,7 +621,11 @@ export abstract class Agent {
async execute (
contract: Address|Partial<ContractInstance>,
message: Message,
options?: ExecOpts
options?: {
execFee?: IFee
execSend?: ICoin[]
execMemo?: string
}
): Promise<unknown> {
if (typeof contract === 'string') contract = new ContractInstance({ address: contract })
if (!contract.address) throw new Error("agent.execute: no contract address")
Expand All @@ -636,15 +638,15 @@ export abstract class Agent {
protected abstract doExecute (
contract: { address: Address },
message: Message,
options?: ExecOpts
options: Parameters<this["execute"]>[2]
): Promise<unknown>

/** Query a contract on the chain. */
query <Q> (
contract: Address|{ address: Address, codeHash?: CodeHash },
msg: Message
message: Message
): Promise<Q> {
return assertChain(this).query(contract, msg)
return assertChain(this).query(contract, message)
}

/** Execute a transaction batch.
Expand All @@ -653,7 +655,6 @@ export abstract class Agent {
batch <B extends Batch> (cb?: BatchCallback<B>): B {
return new this.Batch(this, cb as BatchCallback<Batch>) as unknown as B
}

}

/** Default fees for the main operations that an Agent can perform. */
Expand All @@ -663,15 +664,3 @@ export interface AgentFees {
init?: IFee
exec?: IFee
}

/** Options for a compute transaction. */
export interface ExecOpts {
/** The maximum fee. */
fee?: IFee
/** A list of native tokens to send alongside the transaction. */
send?: ICoin[]
/** A transaction memo. */
memo?: string
/** Allow extra options. */
[k: string]: unknown
}
35 changes: 20 additions & 15 deletions agent/agent-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type {
Into, Name, ICoin, IFee, Label, Class, Address, CodeId, CodeHash, TxHash, Message
} from './agent-base'
import type {
Agent, Chain, ChainId, ChainMode, ExecOpts
Agent, Chain, ChainId, ChainMode,
} from './agent-chain'
import type {
Builder, UploadStore, DeployStore
Expand Down Expand Up @@ -59,11 +59,12 @@ assign.allowed = {
'buildInfo', 'codeHash', 'codePath', 'codeData'
] as Array<keyof CompiledCode>,
ContractUpload: [
'deployment', 'chainId', 'codeId', 'uploadTx', 'uploadBy', 'uploadGas', 'uploadInfo',
'deployment', 'chainId',
'codeId', 'uploadTx', 'uploadBy', 'uploadGas', 'uploadInfo',
] as Array<keyof ContractUpload>,
ContractInstance: [
'name', 'prefix', 'suffix', 'label', 'address',
'initMsg', 'initBy', 'initFunds', 'initFee', 'initMemo', 'initTx', 'initGas'
'codeId', 'codeHash', 'label', 'address', 'initMsg',
'initBy', 'initFunds', 'initFee', 'initMemo', 'initTx', 'initGas'
] as Array<keyof ContractInstance>,
Deployment: [
'name'
Expand Down Expand Up @@ -123,11 +124,11 @@ export class SourceCode {
export class CompiledCode {
buildInfo?: string
/** Code hash uniquely identifying the compiled code. */
codeHash?: CodeHash
codeHash?: CodeHash
/** Location of the compiled code. */
codePath?: string|URL
codePath?: string|URL
/** The compiled code. */
codeData?: Uint8Array
codeData?: Uint8Array

constructor (properties: Partial<CompiledCode> = {}) {
assign(this, properties, assign.allowed['CompiledCode'])
Expand Down Expand Up @@ -199,6 +200,8 @@ export class ContractUpload {
uploadGas?: string|number
/** extra info */
uploadInfo?: string
/** Code hash uniquely identifying the compiled code. */
codeHash?: CodeHash

constructor (properties: Partial<ContractUpload> = {}) {
assign(this, properties, assign.allowed['ContractUpload'])
Expand Down Expand Up @@ -244,12 +247,10 @@ export class ContractUpload {
}

export class ContractInstance {
/** Part of label. */
name?: Name
/** Part of label. */
prefix?: Name
/** Part of label. */
suffix?: Name
/** Code ID representing the identity of the contract's code on a specific chain. */
codeId?: CodeId
/** Code hash uniquely identifying the compiled code. */
codeHash?: CodeHash
/** Full label of the instance. Unique for a given Chain. */
label?: Label
/** Address of this contract instance. Unique per chain. */
Expand Down Expand Up @@ -588,14 +589,18 @@ export class ContractClient {
}

/** Execute a transaction on the specified contract as the specified Agent. */
execute (msg: Message, opt: ExecOpts = {}): Promise<void|unknown> {
execute (message: Message, options: Parameters<Agent["execute"]>[2] = {}): Promise<void|unknown> {
if (!this.agent) {
throw new Error.Missing.Agent(this.constructor?.name)
}
if (!this.contract.address) {
throw new Error.Missing.Address()
}
return this.agent.execute(this.contract as ContractInstance & { address: Address }, msg, opt)
return this.agent.execute(
this.contract as ContractInstance & { address: Address },
message,
options
)
}

}
7 changes: 3 additions & 4 deletions agent/agent-stub.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Address, CodeHash, Message, CodeId, ICoin, Label } from './agent-base'
import { Chain, Agent } from './agent-chain'
import { Batch } from './agent-batch'
import type { ExecOpts } from './agent-chain'
import { ContractUpload, ContractInstance } from './agent-contract'

export class StubChain extends Chain {
Expand Down Expand Up @@ -54,12 +53,12 @@ export class StubAgent extends Agent {
}

/** Stub implementation of sending native token. */
send (to: Address, amounts: ICoin[], opts?: ExecOpts): Promise<void|unknown> {
send (to: Address, amounts: ICoin[], opts?: never): Promise<void|unknown> {
return Promise.resolve()
}

/** Stub implementation of batch send. */
sendMany (outputs: [Address, ICoin[]][], opts?: ExecOpts): Promise<void|unknown> {
sendMany (outputs: [Address, ICoin[]][], opts?: never): Promise<void|unknown> {
return Promise.resolve()
}

Expand Down Expand Up @@ -97,7 +96,7 @@ export class StubAgent extends Agent {
protected doExecute (
contract: { address: Address, codeHash: CodeHash },
message: Message,
options?: ExecOpts
options?: never
): Promise<void|unknown> {
return Promise.resolve({})
}
Expand Down
Loading

0 comments on commit f50f779

Please sign in to comment.