Include ContractExecutionAuthorization among available auth types
This commit is contained in:
parent
ab801768b9
commit
490bd3e84d
@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||||
|
/* eslint-disable no-nested-ternary */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
@ -8,6 +9,14 @@ import { SendAuthorization } from 'cosmjs-types/cosmos/bank/v1beta1/authz'
|
|||||||
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin'
|
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin'
|
||||||
import type { AuthorizationType } from 'cosmjs-types/cosmos/staking/v1beta1/authz'
|
import type { AuthorizationType } from 'cosmjs-types/cosmos/staking/v1beta1/authz'
|
||||||
import { StakeAuthorization, StakeAuthorization_Validators } from 'cosmjs-types/cosmos/staking/v1beta1/authz'
|
import { StakeAuthorization, StakeAuthorization_Validators } from 'cosmjs-types/cosmos/staking/v1beta1/authz'
|
||||||
|
import {
|
||||||
|
AcceptedMessageKeysFilter,
|
||||||
|
AllowAllMessagesFilter,
|
||||||
|
CombinedLimit,
|
||||||
|
ContractExecutionAuthorization,
|
||||||
|
MaxCallsLimit,
|
||||||
|
MaxFundsLimit,
|
||||||
|
} from 'cosmjs-types/cosmwasm/wasm/v1/authz'
|
||||||
import type { AuthorizationMode, GenericAuthorizationType, GrantAuthorizationType } from 'pages/authz/grant'
|
import type { AuthorizationMode, GenericAuthorizationType, GrantAuthorizationType } from 'pages/authz/grant'
|
||||||
|
|
||||||
export interface Msg {
|
export interface Msg {
|
||||||
@ -82,6 +91,82 @@ export function AuthzSendGrantMsg(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function AuthzExecuteContractGrantMsg(
|
||||||
|
granter: string,
|
||||||
|
grantee: string,
|
||||||
|
contract: string,
|
||||||
|
expiration: number,
|
||||||
|
callsRemaining?: number,
|
||||||
|
amounts?: Coin[],
|
||||||
|
allowedMessages?: string[],
|
||||||
|
): Msg {
|
||||||
|
const sendAuthValue = ContractExecutionAuthorization.encode(
|
||||||
|
ContractExecutionAuthorization.fromPartial({
|
||||||
|
grants: [
|
||||||
|
{
|
||||||
|
contract,
|
||||||
|
filter: {
|
||||||
|
typeUrl: allowedMessages
|
||||||
|
? '/cosmwasm.wasm.v1.AcceptedMessageKeysFilter'
|
||||||
|
: '/cosmwasm.wasm.v1.AllowAllMessagesFilter',
|
||||||
|
value: allowedMessages
|
||||||
|
? AcceptedMessageKeysFilter.encode({ keys: allowedMessages }).finish()
|
||||||
|
: AllowAllMessagesFilter.encode({}).finish(),
|
||||||
|
},
|
||||||
|
limit:
|
||||||
|
callsRemaining || amounts
|
||||||
|
? {
|
||||||
|
typeUrl:
|
||||||
|
callsRemaining && amounts
|
||||||
|
? '/cosmwasm.wasm.v1.CombinedLimit'
|
||||||
|
: callsRemaining
|
||||||
|
? '/cosmwasm.wasm.v1.MaxCallsLimit'
|
||||||
|
: '/cosmwasm.wasm.v1.MaxFundsLimit',
|
||||||
|
value:
|
||||||
|
callsRemaining && amounts
|
||||||
|
? CombinedLimit.encode({
|
||||||
|
callsRemaining: BigInt(callsRemaining),
|
||||||
|
amounts,
|
||||||
|
}).finish()
|
||||||
|
: callsRemaining
|
||||||
|
? MaxCallsLimit.encode({
|
||||||
|
remaining: BigInt(callsRemaining),
|
||||||
|
}).finish()
|
||||||
|
: MaxFundsLimit.encode({
|
||||||
|
amounts: amounts || [],
|
||||||
|
}).finish(),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
// limit: undefined is not accepted
|
||||||
|
typeUrl: '/cosmwasm.wasm.v1.MaxCallsLimit',
|
||||||
|
value: MaxCallsLimit.encode({
|
||||||
|
remaining: BigInt(100000),
|
||||||
|
}).finish(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
).finish()
|
||||||
|
|
||||||
|
const grantValue = MsgGrant.fromPartial({
|
||||||
|
grant: {
|
||||||
|
authorization: {
|
||||||
|
typeUrl: '/cosmwasm.wasm.v1.ContractExecutionAuthorization',
|
||||||
|
value: sendAuthValue,
|
||||||
|
},
|
||||||
|
// TODO: fix expiration issue
|
||||||
|
expiration: expiration ? { seconds: BigInt(expiration) } : undefined,
|
||||||
|
},
|
||||||
|
grantee,
|
||||||
|
granter,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
typeUrl: msgAuthzGrantTypeUrl,
|
||||||
|
value: grantValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function AuthzGenericGrantMsg(granter: string, grantee: string, typeURL: string, expiration: number): Msg {
|
export function AuthzGenericGrantMsg(granter: string, grantee: string, typeURL: string, expiration: number): Msg {
|
||||||
return {
|
return {
|
||||||
typeUrl: msgAuthzGrantTypeUrl,
|
typeUrl: msgAuthzGrantTypeUrl,
|
||||||
|
@ -6,19 +6,19 @@
|
|||||||
/* eslint-disable tailwindcss/classnames-order */
|
/* eslint-disable tailwindcss/classnames-order */
|
||||||
/* eslint-disable react/button-has-type */
|
/* eslint-disable react/button-has-type */
|
||||||
|
|
||||||
import { GasPrice, SigningStargateClient } from '@cosmjs/stargate'
|
import { coins, GasPrice, SigningStargateClient } from '@cosmjs/stargate'
|
||||||
import { Alert } from 'components/Alert'
|
import { Alert } from 'components/Alert'
|
||||||
import { Conditional } from 'components/Conditional'
|
import { Conditional } from 'components/Conditional'
|
||||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||||
import { FormControl } from 'components/FormControl'
|
import { FormControl } from 'components/FormControl'
|
||||||
import { NumberInput, TextInput } from 'components/forms/FormInput'
|
import { AddressInput, NumberInput, TextInput } from 'components/forms/FormInput'
|
||||||
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||||
import { InputDateTime } from 'components/InputDateTime'
|
import { InputDateTime } from 'components/InputDateTime'
|
||||||
import { LinkTabs } from 'components/LinkTabs'
|
import { LinkTabs } from 'components/LinkTabs'
|
||||||
import { authzLinkTabs } from 'components/LinkTabs.data'
|
import { authzLinkTabs } from 'components/LinkTabs.data'
|
||||||
import { getConfig } from 'config'
|
import { getConfig } from 'config'
|
||||||
import type { Msg } from 'config/authz'
|
import type { Msg } from 'config/authz'
|
||||||
import { AuthzGenericGrantMsg, AuthzSendGrantMsg } from 'config/authz'
|
import { AuthzExecuteContractGrantMsg, AuthzGenericGrantMsg, AuthzSendGrantMsg } from 'config/authz'
|
||||||
import { useGlobalSettings } from 'contexts/globalSettings'
|
import { useGlobalSettings } from 'contexts/globalSettings'
|
||||||
import type { NextPage } from 'next'
|
import type { NextPage } from 'next'
|
||||||
import { NextSeo } from 'next-seo'
|
import { NextSeo } from 'next-seo'
|
||||||
@ -74,6 +74,22 @@ const Grant: NextPage = () => {
|
|||||||
subtitle: 'The spend limit',
|
subtitle: 'The spend limit',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const maxFundsLimitDenomState = useInputState({
|
||||||
|
id: 'max-funds-limit-denom',
|
||||||
|
name: 'maxFundsLimitDenom',
|
||||||
|
title: 'Max Funds Limit Denom',
|
||||||
|
placeholder: `ustars`,
|
||||||
|
subtitle: 'The denom for max funds limit',
|
||||||
|
})
|
||||||
|
|
||||||
|
const maxFundsLimitState = useNumberInputState({
|
||||||
|
id: 'max-funds-limit',
|
||||||
|
name: 'maxFundsLimit',
|
||||||
|
title: 'Max Funds Limit',
|
||||||
|
placeholder: `1000000`,
|
||||||
|
subtitle: 'The max funds limit for contract execution (leave blank for no limit)',
|
||||||
|
})
|
||||||
|
|
||||||
const allowListState = useInputState({
|
const allowListState = useInputState({
|
||||||
id: 'allow-list',
|
id: 'allow-list',
|
||||||
name: 'allowList',
|
name: 'allowList',
|
||||||
@ -82,6 +98,30 @@ const Grant: NextPage = () => {
|
|||||||
subtitle: 'Comma separated list of addresses to allow transactions to',
|
subtitle: 'Comma separated list of addresses to allow transactions to',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const contractAddressState = useInputState({
|
||||||
|
id: 'contract-address',
|
||||||
|
name: 'contractAddress',
|
||||||
|
title: 'Contract Address',
|
||||||
|
placeholder: `stars1...`,
|
||||||
|
subtitle: 'The contract address to authorize execution on',
|
||||||
|
})
|
||||||
|
|
||||||
|
const allowedMessageKeysState = useInputState({
|
||||||
|
id: 'allowed-message-keys',
|
||||||
|
name: 'allowedMessageKeys',
|
||||||
|
title: 'Allowed Message Keys',
|
||||||
|
placeholder: `mint_to, burn, transfer`,
|
||||||
|
subtitle: 'Comma separated list of allowed message keys (leave blank to allow all)',
|
||||||
|
})
|
||||||
|
|
||||||
|
const callsRemainingState = useNumberInputState({
|
||||||
|
id: 'calls-remaining',
|
||||||
|
name: 'callsRemaining',
|
||||||
|
title: 'Calls Remaining',
|
||||||
|
placeholder: `10`,
|
||||||
|
subtitle: 'The allowed number of contract execution calls (leave blank for no limit)',
|
||||||
|
})
|
||||||
|
|
||||||
const messageToSign = () => {
|
const messageToSign = () => {
|
||||||
if (authType === 'Generic') {
|
if (authType === 'Generic') {
|
||||||
if (genericAuthType === 'MsgSend') {
|
if (genericAuthType === 'MsgSend') {
|
||||||
@ -117,6 +157,16 @@ const Grant: NextPage = () => {
|
|||||||
(expiration?.getTime() as number) / 1000 || 0,
|
(expiration?.getTime() as number) / 1000 || 0,
|
||||||
allowListState.value ? allowListState.value.split(',').map((address) => address.trim()) : [],
|
allowListState.value ? allowListState.value.split(',').map((address) => address.trim()) : [],
|
||||||
)
|
)
|
||||||
|
} else if (authType === 'Execute Smart Contract') {
|
||||||
|
return AuthzExecuteContractGrantMsg(
|
||||||
|
wallet.address || '',
|
||||||
|
granteeAddressState.value,
|
||||||
|
contractAddressState.value,
|
||||||
|
(expiration?.getTime() as number) / 1000 || 0,
|
||||||
|
callsRemainingState.value ? callsRemainingState.value : undefined,
|
||||||
|
maxFundsLimitState.value > 0 ? coins(maxFundsLimitState.value, maxFundsLimitDenomState.value) : undefined,
|
||||||
|
allowedMessageKeysState.value ? allowedMessageKeysState.value.split(',').map((key) => key.trim()) : undefined,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const handleSendMessage = async () => {
|
const handleSendMessage = async () => {
|
||||||
@ -156,9 +206,7 @@ const Grant: NextPage = () => {
|
|||||||
>
|
>
|
||||||
<option value="Generic">Generic</option>
|
<option value="Generic">Generic</option>
|
||||||
<option value="Send">Send</option>
|
<option value="Send">Send</option>
|
||||||
<option disabled value="Execute Smart Contract">
|
<option value="Execute Smart Contract">Execute Smart Contract</option>
|
||||||
Execute Smart Contract
|
|
||||||
</option>
|
|
||||||
<option disabled value="Migrate Smart Contract">
|
<option disabled value="Migrate Smart Contract">
|
||||||
Migrate Smart Contract
|
Migrate Smart Contract
|
||||||
</option>
|
</option>
|
||||||
@ -199,6 +247,15 @@ const Grant: NextPage = () => {
|
|||||||
<TextInput className="w-1/4" {...spendLimitDenomState} />
|
<TextInput className="w-1/4" {...spendLimitDenomState} />
|
||||||
{/* <TextInput className="w-2/5" {...allowListState} /> */}
|
{/* <TextInput className="w-2/5" {...allowListState} /> */}
|
||||||
</Conditional>
|
</Conditional>
|
||||||
|
<Conditional test={authType === 'Execute Smart Contract'}>
|
||||||
|
<AddressInput className="w-2/5" {...contractAddressState} />
|
||||||
|
<TextInput className="w-2/5" {...allowedMessageKeysState} />
|
||||||
|
<NumberInput className="w-2/5" {...callsRemainingState} />
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<NumberInput className="w-2/5" {...maxFundsLimitState} />
|
||||||
|
<TextInput className="w-1/4 ml-2" {...maxFundsLimitDenomState} />
|
||||||
|
</div>
|
||||||
|
</Conditional>
|
||||||
<Conditional test={authType === 'Generic'}>
|
<Conditional test={authType === 'Generic'}>
|
||||||
<FormControl
|
<FormControl
|
||||||
className="w-1/4"
|
className="w-1/4"
|
||||||
|
Loading…
Reference in New Issue
Block a user