Skip to content

Commit

Permalink
Merge pull request #133 from AbstractSDK/adair/useInstallModules
Browse files Browse the repository at this point in the history
Add install modules hook and refine types
  • Loading branch information
adairrr authored Oct 25, 2024
2 parents 862f5a5 + b63ee9b commit 985dc61
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 127 deletions.
6 changes: 6 additions & 0 deletions .changeset/friendly-geese-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@abstract-money/core": minor
"@abstract-money/react": minor
---

Add installModules and update the types for createAccount
8 changes: 3 additions & 5 deletions packages/core/src/actions/account/wallet/enable-ibc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ export async function enableIbc({
...parameters,
modules: [
{
module: {
name: CommonModuleNames.IBC_CLIENT,
namespace: ABSTRACT_NAMESPACE,
version: 'latest',
},
name: CommonModuleNames.IBC_CLIENT,
namespace: ABSTRACT_NAMESPACE,
version: 'latest',
},
],
})
Expand Down
18 changes: 16 additions & 2 deletions packages/core/src/actions/account/wallet/install-modules.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { ExecuteResult, SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { OverrideProperties } from 'type-fest'
import { AccountClient, RegistryTypes } from '../../../codegen/abstract'
import { WithCosmWasmSignOptions } from '../../../types/parameters'
import {
MergedModuleInstallConfig,
moduleInstallConfig,
} from '../../../utils/modules/module-install-config'
import { getAccountClientFromApi } from './get-account-client-from-api'
import { BaseAccountWalletParameters } from './types'

export type InstallModulesParameters = WithCosmWasmSignOptions<
BaseAccountWalletParameters &
Parameters<typeof AccountClient.prototype.installModules>[0]
OverrideProperties<
Parameters<typeof AccountClient.prototype.installModules>[0],
{ modules: MergedModuleInstallConfig[] }
>
>

export async function installModules({
Expand All @@ -17,6 +25,7 @@ export async function installModules({
fee,
memo,
funds,
modules,
...rest
}: InstallModulesParameters): Promise<ExecuteResult> {
const accountClient = await getAccountClientFromApi({
Expand All @@ -25,5 +34,10 @@ export async function installModules({
sender,
apiUrl,
})
return accountClient.installModules(rest, fee, memo, funds)
return accountClient.installModules(
{ modules: modules.map((m) => moduleInstallConfig(m)), ...rest },
fee,
memo,
funds,
)
}
28 changes: 5 additions & 23 deletions packages/core/src/actions/wallet/create-account-monarchy.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,12 @@
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { CamelCasedProperties, OverrideProperties } from 'type-fest'
import { AccountTypes, RegistryTypes } from '../../codegen/abstract'
import { WithCosmWasmSignOptions } from '../../types/parameters'
import { WithOptional } from '../../types/utils'
import { OverrideProperties } from 'type-fest'
import { accountIdToParameter } from '../../utils'
import { createAccount } from './create-account'
import { CreateAccountParameters, createAccount } from './create-account'

export type CreateAccountMonarchyParameters = WithCosmWasmSignOptions<
export type CreateAccountMonarchyParameters = OverrideProperties<
CreateAccountParameters,
{
signingCosmWasmClient: SigningCosmWasmClient
apiUrl: string
sender: string
owner: string
enableIbc?: boolean
} & CamelCasedProperties<
WithOptional<
Omit<
OverrideProperties<
AccountTypes.InstantiateMsg,
{ account_id?: RegistryTypes.AccountId }
>,
'owner'
>,
'install_modules'
>
>
}
>

/**
Expand Down
29 changes: 17 additions & 12 deletions packages/core/src/actions/wallet/create-account.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { CamelCasedProperties, Merge } from 'type-fest'
import { CamelCasedProperties } from 'type-fest'
import { OverrideProperties } from 'type-fest'
import { AccountTypes, RegistryTypes } from '../../codegen/abstract'
import { WithCosmWasmSignOptions } from '../../types/parameters'
import { WithOptional } from '../../types/utils'
import { ABSTRACT_NAMESPACE, accountIdToParameter } from '../../utils'
import { parseCreateAccountExecuteResult } from '../../utils/account-factory/parse-create-account-execute-result'
import { chainIdToName } from '../../utils/chain-registry'
import {
MergedModuleInstallConfig,
moduleInstallConfig,
} from '../../utils/modules/module-install-config'
import { getRegistryAddressFromApi } from '../get-registry-address-from-api'
import { getAppModuleCodeIdFromRegistry } from '../public/get-app-module-code-id-from-registry'
import { CommonModuleNames } from '../public/types'
Expand All @@ -21,9 +25,12 @@ export type CreateAccountParameters = WithCosmWasmSignOptions<
WithOptional<
OverrideProperties<
AccountTypes.InstantiateMsg,
{ account_id?: RegistryTypes.AccountId }
{
account_id?: RegistryTypes.AccountId
install_modules?: MergedModuleInstallConfig[]
}
>,
'install_modules' | 'owner'
'owner'
>
>
>
Expand All @@ -50,17 +57,15 @@ export async function createAccount({
if (
enableIbc &&
!installModules.some(
({ module }) =>
module.name === CommonModuleNames.IBC_CLIENT &&
module.namespace === ABSTRACT_NAMESPACE,
({ name, namespace }) =>
name === CommonModuleNames.IBC_CLIENT &&
namespace === ABSTRACT_NAMESPACE,
)
) {
installModules.push({
module: {
name: CommonModuleNames.IBC_CLIENT,
namespace: ABSTRACT_NAMESPACE,
version: 'latest',
},
name: CommonModuleNames.IBC_CLIENT,
namespace: ABSTRACT_NAMESPACE,
version: 'latest',
})
}

Expand All @@ -82,7 +87,7 @@ export async function createAccount({
monarch: sender,
},
},
install_modules: installModules,
install_modules: installModules.map((m) => moduleInstallConfig(m)),
description,
name,
namespace,
Expand Down
6 changes: 2 additions & 4 deletions packages/core/src/legacy/clients/AbstractAccountClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,9 @@ export class AbstractAccountQueryClient implements IAbstractAccountQueryClient {
*/
public async getOwner(invalidateCache?: boolean): Promise<string | null> {
if (invalidateCache || this._owner === undefined) {
const owner = (await this.accountQueryClient
const governance = await this.accountQueryClient
.ownership()
.then(({ owner }) => owner)) as unknown

const governance = owner as unknown as GovernanceDetails
.then(({ owner }) => owner)

this._owner = match(governance)
.with({ monarchy: { monarch: P.select() } }, (monarch) => monarch)
Expand Down
186 changes: 105 additions & 81 deletions packages/core/src/legacy/clients/AbstractClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ABSTRACT_API_URL,
ABSTRACT_CONSTANTS,
AccountId,
accountIdToString,
} from '@abstract-money/core'
Expand All @@ -20,7 +21,11 @@ import {
createApiClient,
createPublicClient,
} from '../../clients'
import { RegistryClient, RegistryQueryClient } from '../../codegen/abstract'
import {
RegistryClient,
RegistryQueryClient,
RegistryTypes,
} from '../../codegen/abstract'
import { gql } from '../../codegen/gql'
import { assets, chains } from '../../utils/chain-registry'
import { graphqlRequest } from '../api'
Expand Down Expand Up @@ -303,86 +308,105 @@ export class AbstractQueryClient implements IAbstractQueryClient {
}
return account
}
//
// /**
// * Load all local accounts.
// */
// async loadAccounts(
// startAfterSequence?: number,
// count?: number,
// ): Promise<AbstractAccountQueryClient[]> {
// const nextAccountIdSeq = await this.factoryQueryClient
// .config()
// .then(({ local_account_sequence }) => local_account_sequence)
//
// if (startAfterSequence && startAfterSequence >= nextAccountIdSeq) return []
//
// const accounts: AbstractAccountQueryClient[] = []
// for (
// let accountSeq = startAfterSequence ?? 0;
// accountSeq < nextAccountIdSeq;
// accountSeq++
// ) {
// const account = await this.loadAccount(
// await this.localAccountId(accountSeq),
// )
// accounts.push(account)
// if (count && accounts.length >= count) break
// }
//
// return accounts
// }
//
// /**
// * Filter the list of Accounts by the given filter.
// * This method is extremely inefficient if querying live (as opposed to archive) nodes.
// * @param filter
// */
// async filterAccounts(
// filter: AccountFilter,
// ): Promise<AbstractAccountQueryClient[]> {
// const chainName = await this.getChainName()
// const nextAccountIdSeq = await this.factoryQueryClient
// .config()
// .then(({ local_account_sequence }) => local_account_sequence)
//
// const matchingAccounts: AbstractAccountQueryClient[] = []
// for (let accountSeq = 0; accountSeq < nextAccountIdSeq; accountSeq++) {
// const account = await this.loadAccount(
// AbstractAccountId.local(chainName, accountSeq),
// )
//
// if (filter.owner) {
// const owner = await account.getOwner()
// if (owner !== filter.owner) continue
// }
//
// const installedModules =
// filter.moduleIds || filter.modules ? await account.getModules() : []
// const modulesFilter = filter.modules || []
// if (filter.moduleIds) {
// modulesFilter.push(...filter.moduleIds.map((id) => ({ id })))
// }
//
// if (
// modulesFilter.every(({ id, version }) => {
// const installedModule = installedModules.find(
// (module) => module.id === id,
// )
//
// return (
// installedModule &&
// (!version ||
// semverSatisfies(installedModule.version.version, version))
// )
// })
// ) {
// matchingAccounts.push(account)
// }
// }
//
// return matchingAccounts
// }

/**
* Load all local accounts.
*/
async loadAccounts({
startAfter: startAfter_,
}: {
startAfter?: AccountId
} = {}): Promise<AbstractAccountQueryClient[]> {
const chainName = await this.getChainName()
const allAccounts: AbstractAccountQueryClient[] = []
let startAfter: RegistryTypes.AccountId | undefined = startAfter_
let hasMore = true

while (hasMore) {
const { accounts } = await this.registryQueryClient.accountList({
limit: ABSTRACT_CONSTANTS.MAX_PAGE_SIZE,
startAfter,
})

// Add current batch to the overall list
const accountQueryClients = accounts.map(
([accountId, address]) =>
new AbstractAccountQueryClient({
abstract: this,
accountId: {
...accountId,
chainName,
},
accountAddress: address,
}),
)

// Cache the clients
accountQueryClients.map((q) => {
this.accountCache.set(accountIdToString(q.accountId), q)
})

allAccounts.push(...accountQueryClients)

// Check if we've reached the end of the list
if (accounts.length < ABSTRACT_CONSTANTS.MAX_PAGE_SIZE) {
hasMore = false
} else {
// Set startAfter to the last account in the current batch to get the next page
// @ts-ignore
startAfter = accounts[accounts.length - 1][0]
}
}

return allAccounts
}

/**
* Filter the list of Accounts by the given filter.
* This method is extremely inefficient if querying live (as opposed to archive) nodes.
* @param filter
*/
async filterAccounts(
filter: AccountFilter,
): Promise<AbstractAccountQueryClient[]> {
const chainName = await this.getChainName()

const allAccounts = await this.loadAccounts()

const matchingAccounts: AbstractAccountQueryClient[] = []

for (const account of allAccounts) {
if (filter.owner) {
const owner = await account.getOwner()
if (owner !== filter.owner) continue
}

const installedModules =
filter.moduleIds || filter.modules ? await account.getModules() : []
const modulesFilter = filter.modules || []
if (filter.moduleIds) {
modulesFilter.push(...filter.moduleIds.map((id) => ({ id })))
}

if (
modulesFilter.every(({ id, version }) => {
const installedModule = installedModules.find(
(module) => module.id === id,
)

return (
installedModule &&
(!version ||
semverSatisfies(installedModule.version.version, version))
)
})
) {
matchingAccounts.push(account)
}
}

return matchingAccounts
}

/**
* Upgrade the abstract client to an executable client.
Expand Down
Loading

0 comments on commit 985dc61

Please sign in to comment.