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: add ibc executions #74

Merged
merged 24 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,57 @@ export function CosmosKitProvider(props: { children: ReactNode }) {
const signerOptions = {
signingCosmwasm: (chain: Chain) => {
switch (chain.chain_name) {
case 'localjuno':
case 'junotestnet':
return { gasPrice: GasPrice.fromString('0.1ujunox') }
case 'juno':
return { gasPrice: GasPrice.fromString('0.1ujuno') }
case 'osmosis':
case 'osmosistestnet':
case 'osmosistestnet5':
return { gasPrice: GasPrice.fromString('0.035uosmo') }
case 'neutron':
return {
gasPrice: GasPrice.fromString('0.01untrn'),
}
case 'neutrontestnet':
return { gasPrice: GasPrice.fromString('.5untrn') }
case 'archwaytestnet':
return { gasPrice: GasPrice.fromString(`${1e12}aconst`) }
case 'archway':
return { gasPrice: GasPrice.fromString(`${1e12}aarch`) }
}
},
}
return (
<ChainProvider
chains={chains}
chains={chains.map((chain) => {
return {
...chain,
apis: {
...chain.apis,
rpc: chain.apis?.rpc?.length
? [
chain.apis.rpc.find((rpc) =>
rpc.address.includes('polkachu'),
) ?? chain.apis.rpc[0],
]
: [],
Comment on lines +40 to +46
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that looks odd, why do we have to do that?

},
}
})}
assetLists={assets}
wallets={wallets}
signerOptions={signerOptions}
sessionOptions={{
duration: 1000 * 60 * 60 * 24 * 7,
}}
endpointOptions={{
isLazy: true,
endpoints: {
archway: {
rpc: ['https://archway-rpc.polkachu.com'],
isLazy: true,
},
},
}}
{...props}
/>
)
Expand Down
5 changes: 4 additions & 1 deletion examples/wagemos-cosmoskit-nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ const poppins = Poppins({
weight: ['900', '800', '700'],
variable: '--font-display',
})
const abstractConfig = createConfig({ provider: cosmosKitProvider })
const abstractConfig = createConfig({
provider: cosmosKitProvider,
apiUrl: 'https://api.abstract.money/graphql',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i actually think it makes sense exporting mainnetApiUrl and testnetApiUrl from the SDK itself. most likely those are the ones devs will use in future. something to consider.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

})

export default function RootLayout({
children,
Expand Down
126 changes: 126 additions & 0 deletions examples/wagemos-cosmoskit-nextjs/src/app/remote/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
'use client'
import {
useAccounts,
useCreateRemoteAccount,
useExecuteOnRemote,
useRemoteAccountIds,
useRemoteHosts,
} from '@abstract-money/react'
import { useChain } from '@cosmos-kit/react'
import { useCallback, useMemo, useState } from 'react'
import { Button } from '../../components/ui/button'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '../../components/ui/select'
import { WalletButton } from '../_components/wallet-button'

const CHAIN_NAME = 'neutron'
export default function RemotePage() {
const { data: remoteHosts, isLoading, refetch } = useRemoteHosts(CHAIN_NAME)
const [chainInput, setChainInput] = useState(remoteHosts?.[0]?.[0])

const { address } = useChain(CHAIN_NAME)

const { data: accounts, status } = useAccounts({
args: {
chainName: CHAIN_NAME,
owner: address ?? '',
},
dalechyn marked this conversation as resolved.
Show resolved Hide resolved
query: {
enabled: !!address,
},
})

const firstAccount = useMemo(() => accounts?.[0][accounts])

const { mutate: createRemoteAccount, isLoading: isCreating } =
useCreateRemoteAccount({
accountId: firstAccount,
chainName: firstAccount?.chainName,
})
const { mutate: execRemote, isLoading: isExecuting } = useExecuteOnRemote({
accountId: firstAccount,
chainName: firstAccount?.chainName,
})

const { data: remoteAccountIds } = useRemoteAccountIds({
args: {},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note for self in future, in such cases we should default to {} and have user to not pass any args at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accountId: firstAccount,
chainName: firstAccount?.chainName,
})

const onCreateClick = useCallback(() => {
if (!chainInput) {
throw new Error('chainInput is undefined')
}

console.log('creating remote account')

createRemoteAccount({
fee: 'auto',
funds: [],
args: {
hostChainName: chainInput,
base_asset: 'juno>juno',
},
})
}, [createRemoteAccount, chainInput])

const onExecClick = useCallback(() => {
if (!chainInput) {
throw new Error('chainInput is undefined')
}
console.log('executing remote account')
execRemote({
funds: [],
fee: 'auto',
args: {
hostChainName: chainInput,
managerMsg: {
update_info: {
name: 'test',
},
},
},
})
}, [execRemote, chainInput])

return (
<>
<h3>Host</h3>
<Select onValueChange={setChainInput} defaultValue={chainInput}>
<SelectTrigger>
<SelectValue placeholder="Select a host" />
</SelectTrigger>
<SelectContent>
{remoteHosts?.map(([chainName]) => {
return (
<SelectItem key={chainName} value={chainName}>
{chainName}
</SelectItem>
)
})}
</SelectContent>
</Select>
{isLoading && <div>Loading...</div>}
{/*<Input placeholder="chain" value={chainInput} onChange={(e) => setChainInput(e.target.value)} />*/}
<Button onClick={onCreateClick} disabled={!chainInput || isCreating}>
Creat{isCreating ? 'ing' : 'e'} Remote Account {isCreating && '...'}
</Button>
<Button onClick={onExecClick} disabled={!chainInput || isExecuting}>
Updat{isExecuting ? 'ing' : 'e'} Remote Account {isExecuting && '...'}
</Button>
adairrr marked this conversation as resolved.
Show resolved Hide resolved

<WalletButton />
<h3>Remote Accounts</h3>
<div>
<pre>{JSON.stringify(remoteAccountIds, null, 2)}</pre>
</div>
<Button onClick={() => refetch()}>Refresh</Button>
</>
)
}
2 changes: 1 addition & 1 deletion examples/wagemos-graz-nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cosmjs-types": "^0.8.0",
"graz": "^0.1.1",
"graz": "^0.1.5",
"long": "^5.2.3",
"lucide-react": "^0.293.0",
"next": "14.0.3",
Expand Down
34 changes: 34 additions & 0 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,37 @@ npm i -g @abstract-money/cli
```

## Usage

### Create `abstract.config.ts` in the root of your project

```typescript
import { defineConfig } from '@abstract-money/cli'
import { react, registry } from '@abstract-money/cli/plugins'

export default defineConfig({
// Where to output the generated files
out: 'src/generated',
plugins: [
// Add plugins here
react(),
registry({
contracts: [
// Add contracts and versions here
{
name: 'carrot-app',
namespace: 'abstract',
version: '0.1.0',
},
],
}),
],
})
```

### Generate

Generate the files

```bash
abstract generate
```
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
IbcClientQueryClient,
VersionControlTypes,
} from '../../../codegen/abstract'
import { getIbcClientQueryClient } from '../../public/get-ibc-client-query-client'
import { CommonModuleNames } from '../../public/types'
import { getModuleAddress } from './get-module-address'

export type GetIbcClientQueryClientFromManagerParameters = {
Expand All @@ -11,8 +13,6 @@ export type GetIbcClientQueryClientFromManagerParameters = {
apiUrl: string
}

const IBC_CLIENT_MODULE_ID = 'abstract:ibc-client'

/**
* Retrieve the {@link IbcClientQueryClient} from the manager account.
* @throws if the IBC-client module is not installed
Expand All @@ -29,12 +29,15 @@ export async function getIbcClientQueryClientFromManager({
accountId,
cosmWasmClient,
apiUrl,
id: IBC_CLIENT_MODULE_ID,
id: CommonModuleNames.IBC_CLIENT,
})

if (!ibcClientAddress) {
throw new Error('IBC-client module not installed')
}

return new IbcClientQueryClient(cosmWasmClient, ibcClientAddress)
return getIbcClientQueryClient({
cosmWasmClient,
ibcClientAddress,
})
}
60 changes: 60 additions & 0 deletions packages/core/src/actions/account/wallet/create-remote-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { IbcClientTypes } from '../../../codegen/abstract'
import { WithCosmWasmSignOptions } from '../../../types/parameters'
import { executeIbcAction } from './execute-ibc-action'
import { BaseWalletParameters } from './types'

export type CreateRemoteAccountParameters = Omit<
WithCosmWasmSignOptions<
BaseWalletParameters &
Omit<
Extract<IbcClientTypes.ExecuteMsg, { register: unknown }>['register'],
'host_chain' | 'install_modules'
> & {
hostChainName: string
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to call this remoteChainName

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to stick with the names that we have in the contract to avoid confusion.

we can provide this one as an alias maybe.

// for some reason we cannot use the `install_modules` type from the IbcClientTypes
installModules?: IbcClientTypes.ModuleInstallConfig[]
}
>,
'funds'
>

/**
* Create a remote account.
* @param accountId
* @param signingCosmWasmClient
* @param apiUrl
* @param sender
* @param hostChainName
* @param registerMsgParams
* @param fee
* @param memo
*/
export async function createRemoteAccount({
accountId,
signingCosmWasmClient,
apiUrl,
sender,
hostChainName,
installModules,
fee,
memo,
...registerMsgParams
}: CreateRemoteAccountParameters) {
const registerMsg: IbcClientTypes.ExecuteMsg = {
register: {
host_chain: hostChainName,
install_modules: installModules ?? [],
...registerMsgParams,
},
}

return executeIbcAction({
accountId,
signingCosmWasmClient,
apiUrl,
sender,
msgs: registerMsg,
fee,
memo,
})
}
18 changes: 7 additions & 11 deletions packages/core/src/actions/account/wallet/create-sub-account.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { ManagerClient, VersionControlTypes } from '../../../codegen/abstract'
import { ManagerClient } from '../../../codegen/abstract'
import { WithCosmWasmSignOptions } from '../../../types/parameters'
import { getManagerClientFromApi } from './get-manager-client-from-api'
import { BaseWalletParameters } from './types'

export type CreateSubAccountParameters = WithCosmWasmSignOptions<
{
accountId: VersionControlTypes.AccountId
signingCosmWasmClient: SigningCosmWasmClient
apiUrl: string
sender: string
} & Omit<
Parameters<typeof ManagerClient.prototype.createSubAccount>[0],
'accountId'
> & { subAccountId?: number }
BaseWalletParameters &
Omit<
Parameters<typeof ManagerClient.prototype.createSubAccount>[0],
'accountId'
> & { subAccountId?: number }
>

export async function createSubAccount({
Expand Down
15 changes: 6 additions & 9 deletions packages/core/src/actions/account/wallet/deposit.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { VersionControlTypes } from '../../../codegen/abstract'
import { WithCosmWasmSignOptions } from '../../../types/parameters'
import { Asset, encodeAssetsTransfersMsgs } from '../../../utils/assets'
import { getAccountBaseAddressesFromApi } from '../public/get-account-base-addresses-from-api'
import { BaseWalletParameters } from './types'

export type DepositParameters = Omit<
WithCosmWasmSignOptions<{
accountId: VersionControlTypes.AccountId
signingCosmWasmClient: SigningCosmWasmClient
apiUrl: string
sender: string
assets: Asset[]
}>,
WithCosmWasmSignOptions<
BaseWalletParameters & {
assets: Asset[]
}
>,
'funds'
>

Expand Down
Loading