Skip to content

Commit

Permalink
refactor(agent,scrt,cw): common implementation of Chain#ready
Browse files Browse the repository at this point in the history
- deduplicate
- maybe in this case it's possible to give Chain a .then() method
that resolves to this + this.api, effectively giving an async constructor?
  • Loading branch information
egasimus committed Oct 23, 2023
1 parent fc6243f commit 9aae1a3
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 49 deletions.
29 changes: 29 additions & 0 deletions agent/agent-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,30 @@ export abstract class Chain {
/** Return self. */
get chain () { return this }

api?: unknown

abstract getApi (): unknown

get ready () {
if (this.isDevnet && !this.devnet) {
throw new Error("the chain is marked as a devnet but is missing the devnet handle")
}
type This = this
type ThisWithApi = This & { api: NonNullable<This["api"]> }
const init = new Promise<ThisWithApi>(async (resolve, reject)=>{
if (this.isDevnet) {
await this.devnet!.start()
}
if (!this.api) {
if (!this.url) throw new Error("the chain's url property is not set")
this.api = await Promise.resolve(this.getApi())
}
return resolve(this as ThisWithApi)
})
Object.defineProperty(this, 'ready', { get () { return init } })
return init
}

/** Wait for the block height to increment. */
get nextBlock (): Promise<number> {
return this.height.then(async startingHeight=>{
Expand Down Expand Up @@ -296,6 +320,11 @@ export class StubChain extends Chain {

defaultDenom = 'stub'

getApi (): {} {
this.log.warn('chain.getApi: this function is stub; use a subclass of Chain')
return Promise.resolve({})
}

/** Get the current block height. */
get height (): Promise<number> {
this.log.warn('chain.height: this getter is stub; use a subclass of Chain')
Expand Down
23 changes: 3 additions & 20 deletions connect/cw/cw-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,10 @@ class CWChain extends Chain {
defaultDenom = ''

/** Query-only API handle. */
api?: CosmWasmClient
declare api?: CosmWasmClient

/** One-shot async initialization of chain.
* Populates the `api` property with a CosmWasmClient. */
get ready (): Promise<this & { api: CosmWasmClient }> {
if (this.isDevnet && !this.devnet) {
throw new Error("the chain is marked as a devnet but is missing the devnet handle")
}
const init = new Promise<this & { api: CosmWasmClient }>(async (resolve, reject)=>{
if (this.isDevnet) {
await this.devnet!.start()
}
if (!this.api) {
if (!this.url) throw new CWError("the chain's url property is not set")
const api = await CosmWasmClient.connect(this.url)
this.api = api
}
return resolve(this as this & { api: CosmWasmClient })
})
Object.defineProperty(this, 'ready', { get () { return init } })
return init
async getApi (): Promise<CosmWasmClient> {
return await CosmWasmClient.connect(this.url)
}

get block (): Promise<Block> {
Expand Down
37 changes: 8 additions & 29 deletions connect/scrt/scrt-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,33 +35,7 @@ class ScrtChain extends Chain {
Agent: AgentClass<ScrtAgent> = ScrtChain.Agent

/** A fresh instance of the anonymous read-only API client. Memoize yourself. */
api?: SecretNetworkClient

constructor (options: Partial<ScrtChain> = {
url: ScrtChain.Config.defaultMainnetUrl,
mode: Chain.Mode.Mainnet
}) {
super(options)
this.log.label = `${this.id}`
}

get ready (): Promise<this & { api: SecretNetworkClient }> {
if (this.isDevnet && !this.devnet) {
throw new Error("the chain is marked as a devnet but is missing the devnet handle")
}
const init = new Promise<this & { api: SecretNetworkClient }>(async (resolve, reject)=>{
if (this.isDevnet) {
await this.devnet!.start()
}
if (!this.api) {
if (!this.url) throw new Error("the chain's url property is not set")
this.api = this.getApi()
}
return resolve(this as this & { api: SecretNetworkClient })
})
Object.defineProperty(this, 'ready', { get () { return init } })
return init
}
declare api?: SecretNetworkClient

/** @returns a fresh instance of the anonymous read-only API client. */
getApi (options: Partial<CreateClientOptions> = {}): SecretNetworkClient {
Expand Down Expand Up @@ -185,13 +159,18 @@ export type { TxResponse }
/** Represents a connection to the Secret Network,
* authenticated as a specific address. */
class ScrtAgent extends Agent {

log = new Console('ScrtAgent')

/** Downcast chain property to Scrt only. */
declare chain: ScrtChain

/** Batch class used by this agent. */
Batch: BatchClass<ScrtBatch> = ScrtAgent.Batch

/** Whether to simulate each execution first to get a more accurate gas estimate. */
simulateForGas: boolean = false

/** Default fees for this agent. */
fees = ScrtChain.defaultFees

Expand All @@ -208,10 +187,10 @@ class ScrtAgent extends Agent {
}

get ready (): Promise<this & { api: SecretNetworkClient }> {
// Require chain reference to be populated.
if (!this.chain) throw new Error.Missing.Chain()
// If an API instance is already available (e.g. provided to constructor), just use that.
if (this.api) return Promise.resolve(this as this & { api: SecretNetworkClient })
// Require chain reference to be populated.
if (!this.chain) throw new Error.Missing.Chain()
// Begin asynchronous init.
const init = new Promise<this & { api: SecretNetworkClient }>(async (
resolve, reject
Expand Down
4 changes: 4 additions & 0 deletions connect/scrt/scrt-mocknet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ export class Mocknet extends Chain {
)
}
}

getApi () {
return Promise.resolve({})
}
}

class MocknetAgent extends Agent {
Expand Down

0 comments on commit 9aae1a3

Please sign in to comment.