Initial authz logic
This commit is contained in:
parent
d8afd9f637
commit
680b2ac258
@ -158,3 +158,16 @@ export const royaltyRegistryLinkTabs: LinkTabProps[] = [
|
||||
href: '/contracts/royaltyRegistry/execute',
|
||||
},
|
||||
]
|
||||
|
||||
export const authzLinkTabs: LinkTabProps[] = [
|
||||
{
|
||||
title: 'Grant',
|
||||
description: `Grant authorizations to a given address`,
|
||||
href: '/authz/grant',
|
||||
},
|
||||
{
|
||||
title: 'Revoke',
|
||||
description: `Revoke already granted authorizations`,
|
||||
href: '/authz/revoke',
|
||||
},
|
||||
]
|
||||
|
160
config/authz.ts
Normal file
160
config/authz.ts
Normal file
@ -0,0 +1,160 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import { GenericAuthorization } from 'cosmjs-types/cosmos/authz/v1beta1/authz'
|
||||
import { MsgGrant } from 'cosmjs-types/cosmos/authz/v1beta1/tx'
|
||||
import { SendAuthorization } from 'cosmjs-types/cosmos/bank/v1beta1/authz'
|
||||
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin'
|
||||
import type { AuthorizationType } from 'cosmjs-types/cosmos/staking/v1beta1/authz'
|
||||
import { StakeAuthorization, StakeAuthorization_Validators } from 'cosmjs-types/cosmos/staking/v1beta1/authz'
|
||||
import type { AuthorizationMode, GenericAuthorizationType, GrantAuthorizationType } from 'pages/authz/grant'
|
||||
|
||||
export interface Msg {
|
||||
typeUrl: string
|
||||
value: any
|
||||
}
|
||||
|
||||
export interface AuthzMessage {
|
||||
authzMode: AuthorizationMode
|
||||
authzType: GrantAuthorizationType
|
||||
displayName: string
|
||||
typeUrl: string
|
||||
genericAuthzType?: GenericAuthorizationType
|
||||
}
|
||||
|
||||
export const grantGenericStakeAuthorization: AuthzMessage = {
|
||||
authzMode: 'Grant',
|
||||
authzType: 'Generic',
|
||||
displayName: 'Stake',
|
||||
typeUrl: '/cosmos.staking.v1beta1.MsgDelegate',
|
||||
genericAuthzType: 'MsgDelegate',
|
||||
}
|
||||
|
||||
export const grantGenericSendAuthorization: AuthzMessage = {
|
||||
authzMode: 'Grant',
|
||||
authzType: 'Generic',
|
||||
displayName: 'Send',
|
||||
typeUrl: '/cosmos.bank.v1beta1.MsgSend',
|
||||
genericAuthzType: 'MsgSend',
|
||||
}
|
||||
|
||||
export const authzMessages: AuthzMessage[] = [grantGenericStakeAuthorization, grantGenericSendAuthorization]
|
||||
|
||||
const msgAuthzGrantTypeUrl = '/cosmos.authz.v1beta1.MsgGrant'
|
||||
|
||||
export function AuthzSendGrantMsg(
|
||||
granter: string,
|
||||
grantee: string,
|
||||
denom: string,
|
||||
spendLimit: number,
|
||||
expiration: number,
|
||||
): Msg {
|
||||
const sendAuthValue = SendAuthorization.encode(
|
||||
SendAuthorization.fromPartial({
|
||||
spendLimit: [
|
||||
Coin.fromPartial({
|
||||
amount: String(spendLimit),
|
||||
denom,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
).finish()
|
||||
const grantValue = MsgGrant.fromPartial({
|
||||
grant: {
|
||||
authorization: {
|
||||
typeUrl: '/cosmos.bank.v1beta1.SendAuthorization',
|
||||
value: sendAuthValue,
|
||||
},
|
||||
//expiration: { seconds: BigInt(expiration).valueOf() },
|
||||
},
|
||||
grantee,
|
||||
granter,
|
||||
})
|
||||
|
||||
return {
|
||||
typeUrl: msgAuthzGrantTypeUrl,
|
||||
value: grantValue,
|
||||
}
|
||||
}
|
||||
|
||||
export function AuthzGenericGrantMsg(granter: string, grantee: string, typeURL: string, expiration: number): Msg {
|
||||
return {
|
||||
typeUrl: msgAuthzGrantTypeUrl,
|
||||
value: {
|
||||
grant: {
|
||||
authorization: {
|
||||
typeUrl: '/cosmos.authz.v1beta1.GenericAuthorization',
|
||||
value: GenericAuthorization.encode(
|
||||
GenericAuthorization.fromPartial({
|
||||
msg: typeURL,
|
||||
}),
|
||||
).finish(),
|
||||
},
|
||||
expiration: expiration ? { seconds: expiration } : undefined,
|
||||
},
|
||||
grantee,
|
||||
granter,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function AuthzStakeGrantMsg({
|
||||
expiration,
|
||||
grantee,
|
||||
granter,
|
||||
allowList,
|
||||
denyList,
|
||||
maxTokens,
|
||||
denom,
|
||||
stakeAuthzType,
|
||||
}: {
|
||||
granter: string
|
||||
grantee: string
|
||||
expiration: number
|
||||
allowList?: string[]
|
||||
denyList?: string[]
|
||||
maxTokens?: string
|
||||
denom?: string
|
||||
stakeAuthzType: AuthorizationType
|
||||
}): Msg {
|
||||
const allow_list = StakeAuthorization_Validators.encode(
|
||||
StakeAuthorization_Validators.fromPartial({
|
||||
address: allowList,
|
||||
}),
|
||||
).finish()
|
||||
const deny_list = StakeAuthorization_Validators.encode(
|
||||
StakeAuthorization_Validators.fromPartial({
|
||||
address: denyList,
|
||||
}),
|
||||
).finish()
|
||||
const stakeAuthValue = StakeAuthorization.encode(
|
||||
StakeAuthorization.fromPartial({
|
||||
authorizationType: stakeAuthzType,
|
||||
allowList: allowList?.length ? StakeAuthorization_Validators.decode(allow_list) : undefined,
|
||||
denyList: denyList?.length ? StakeAuthorization_Validators.decode(deny_list) : undefined,
|
||||
maxTokens: maxTokens
|
||||
? Coin.fromPartial({
|
||||
amount: maxTokens,
|
||||
denom,
|
||||
})
|
||||
: undefined,
|
||||
}),
|
||||
).finish()
|
||||
const grantValue = MsgGrant.fromPartial({
|
||||
grant: {
|
||||
authorization: {
|
||||
typeUrl: '/cosmos.staking.v1beta1.StakeAuthorization',
|
||||
value: stakeAuthValue,
|
||||
},
|
||||
// expiration: { seconds: BigInt(expiration) },
|
||||
},
|
||||
grantee,
|
||||
granter,
|
||||
})
|
||||
|
||||
return {
|
||||
typeUrl: msgAuthzGrantTypeUrl,
|
||||
value: grantValue,
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
"@cosmjs/math": "^0",
|
||||
"@cosmjs/proto-signing": "^0",
|
||||
"@cosmjs/stargate": "^0",
|
||||
"cosmjs-types": "0.9.0",
|
||||
"@cosmos-kit/keplr": "^2.4.4",
|
||||
"@cosmos-kit/leap": "^2.4.3",
|
||||
"@cosmos-kit/leap-metamask-cosmos-snap": "^0.3.3",
|
||||
|
221
pages/authz/grant.tsx
Normal file
221
pages/authz/grant.tsx
Normal file
@ -0,0 +1,221 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable tailwindcss/classnames-order */
|
||||
/* eslint-disable react/button-has-type */
|
||||
|
||||
import { GasPrice, SigningStargateClient } from '@cosmjs/stargate'
|
||||
import { Alert } from 'components/Alert'
|
||||
import { Conditional } from 'components/Conditional'
|
||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||
import { FormControl } from 'components/FormControl'
|
||||
import { TextInput } from 'components/forms/FormInput'
|
||||
import { useInputState } from 'components/forms/FormInput.hooks'
|
||||
import { InputDateTime } from 'components/InputDateTime'
|
||||
import { LinkTabs } from 'components/LinkTabs'
|
||||
import { authzLinkTabs } from 'components/LinkTabs.data'
|
||||
import { getConfig } from 'config'
|
||||
import type { Msg } from 'config/authz'
|
||||
import { AuthzGenericGrantMsg } from 'config/authz'
|
||||
import { useGlobalSettings } from 'contexts/globalSettings'
|
||||
import type { NextPage } from 'next'
|
||||
import { NextSeo } from 'next-seo'
|
||||
import { useState } from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import { NETWORK } from 'utils/constants'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
export type AuthorizationMode = 'Grant' | 'Revoke'
|
||||
export type GrantAuthorizationType = 'Generic' | 'Send' | 'Execute Smart Contract' | 'Migrate Smart Contract'
|
||||
export type GenericAuthorizationType =
|
||||
| 'MsgDelegate'
|
||||
| 'MsgUndelegate'
|
||||
| 'MsgBeginRedelegate'
|
||||
| 'MsgWithdrawDelegatorReward'
|
||||
| 'MsgVote'
|
||||
| 'MsgSend'
|
||||
| 'MsgExecuteContract'
|
||||
| 'MsgMigrateContract'
|
||||
|
||||
const Grant: NextPage = () => {
|
||||
const wallet = useWallet()
|
||||
const { timezone } = useGlobalSettings()
|
||||
|
||||
const [authMode, setAuthMode] = useState<AuthorizationMode>('Grant')
|
||||
const [authType, setAuthType] = useState<GrantAuthorizationType>('Generic')
|
||||
const [genericAuthType, setGenericAuthType] = useState<GenericAuthorizationType>('MsgSend')
|
||||
const [expiration, setExpiration] = useState<Date | undefined>()
|
||||
const [transactionHash, setTransactionHash] = useState<string | undefined>(undefined)
|
||||
|
||||
const granteeAddressState = useInputState({
|
||||
id: 'grantee-address',
|
||||
name: 'granteeAddress',
|
||||
title: 'Grantee Address',
|
||||
placeholder: 'stars1...',
|
||||
subtitle: 'The address to grant authorization to',
|
||||
})
|
||||
|
||||
const spendLimitDenomState = useInputState({
|
||||
id: 'spend-limit-denom',
|
||||
name: 'spendLimitDenom',
|
||||
title: 'Spend Limit Denom',
|
||||
placeholder: `ustars`,
|
||||
subtitle: 'The spend limit denom',
|
||||
})
|
||||
|
||||
const messageToSign = () => {
|
||||
if (authType === 'Generic') {
|
||||
if (genericAuthType === 'MsgSend') {
|
||||
return AuthzGenericGrantMsg(
|
||||
wallet.address || '',
|
||||
granteeAddressState.value,
|
||||
'/cosmos.bank.v1beta1.MsgSend',
|
||||
(expiration?.getTime() as number) / 1000 || 0,
|
||||
)
|
||||
}
|
||||
if (genericAuthType === 'MsgDelegate') {
|
||||
return AuthzGenericGrantMsg(
|
||||
wallet.address || '',
|
||||
granteeAddressState.value,
|
||||
'/cosmos.staking.v1beta1.MsgDelegate',
|
||||
(expiration?.getTime() as number) / 1000 || 0,
|
||||
)
|
||||
}
|
||||
if (genericAuthType === 'MsgUndelegate') {
|
||||
return AuthzGenericGrantMsg(
|
||||
wallet.address || '',
|
||||
granteeAddressState.value,
|
||||
'/cosmos.staking.v1beta1.MsgUndelegate',
|
||||
(expiration?.getTime() as number) / 1000 || 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleSendMessage = async () => {
|
||||
try {
|
||||
if (!wallet.isWalletConnected) return toast.error('Please connect your wallet.')
|
||||
setTransactionHash(undefined)
|
||||
const offlineSigner = wallet.getOfflineSignerDirect()
|
||||
const stargateClient = await SigningStargateClient.connectWithSigner(getConfig(NETWORK).rpcUrl, offlineSigner, {
|
||||
gasPrice: GasPrice.fromString('0.025ustars'),
|
||||
})
|
||||
|
||||
const response = await stargateClient.signAndBroadcast(wallet.address || '', [messageToSign() as Msg], 'auto')
|
||||
setTransactionHash(response.transactionHash)
|
||||
toast.success(`${authType} authorization success.`, { style: { maxWidth: 'none' } })
|
||||
} catch (error: any) {
|
||||
toast.error(error.message, { style: { maxWidth: 'none' } })
|
||||
setTransactionHash(undefined)
|
||||
console.error('Error: ', error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="px-4 pt-4 pb-16 mx-auto space-y-8 ml-8 w-full">
|
||||
<NextSeo title="Authorization" />
|
||||
<ContractPageHeader
|
||||
description="Here you can grant and revoke authorizations."
|
||||
link="https://docs.stargaze.zone/developers/authz"
|
||||
title="Authorization"
|
||||
/>
|
||||
<LinkTabs activeIndex={0} data={authzLinkTabs} />
|
||||
<div className="flex flex-col w-1/4">
|
||||
<span className="text-xl font-bold text-white">Authorization Type</span>
|
||||
<select
|
||||
className="mt-2 pt-2 pb-2 px-4 placeholder:text-white/50 bg-white/10 rounded border-2 border-white/20 focus:ring focus:ring-plumbus-20"
|
||||
onChange={(e) => setAuthType(e.target.value as GrantAuthorizationType)}
|
||||
value={authType}
|
||||
>
|
||||
<option value="Generic">Generic</option>
|
||||
<option disabled value="Send">
|
||||
Send
|
||||
</option>
|
||||
<option disabled value="Execute Smart Contract">
|
||||
Execute Smart Contract
|
||||
</option>
|
||||
<option disabled value="Migrate Smart Contract">
|
||||
Migrate Smart Contract
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<Conditional test={authType === 'Generic'}>
|
||||
<div className="flex flex-col w-1/4">
|
||||
<span className="text-lg font-bold text-white">Generic Authorization Type</span>
|
||||
<select
|
||||
className="mt-2 pt-2 pb-2 px-4 placeholder:text-white/50 bg-white/10 rounded border-2 border-white/20 focus:ring focus:ring-plumbus-20"
|
||||
onChange={(e) => setGenericAuthType(e.target.value as GenericAuthorizationType)}
|
||||
value={genericAuthType}
|
||||
>
|
||||
<option value="MsgSend">Send</option>
|
||||
<option value="MsgDelegate">Delegate</option>
|
||||
<option value="MsgUndelegate">Undelegate</option>
|
||||
<option disabled value="MsgBeginRedelegate">
|
||||
Redelegate
|
||||
</option>
|
||||
<option disabled value="MsgWithdrawDelegatorReward">
|
||||
Withdraw Delegator Reward
|
||||
</option>
|
||||
<option disabled value="MsgVote">
|
||||
Vote
|
||||
</option>
|
||||
<option disabled value="MsgExecuteContract">
|
||||
Execute Contract
|
||||
</option>
|
||||
<option disabled value="MsgMigrateContract">
|
||||
Migrate Contract
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</Conditional>
|
||||
<TextInput className="w-1/3" {...granteeAddressState} />
|
||||
<Conditional test={authType === 'Send'}>
|
||||
<TextInput className="w-1/4" {...spendLimitDenomState} />
|
||||
</Conditional>
|
||||
<FormControl
|
||||
className="w-1/4"
|
||||
htmlId="expiration"
|
||||
subtitle={`Expiration time for the authorization ${timezone === 'Local' ? '(local)' : '(UTC)'}`}
|
||||
title="Expiration Time (Optional)"
|
||||
>
|
||||
<InputDateTime
|
||||
minDate={
|
||||
timezone === 'Local' ? new Date() : new Date(Date.now() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
}
|
||||
onChange={(date) =>
|
||||
date
|
||||
? setExpiration(
|
||||
timezone === 'Local' ? date : new Date(date?.getTime() - new Date().getTimezoneOffset() * 60 * 1000),
|
||||
)
|
||||
: setExpiration(undefined)
|
||||
}
|
||||
value={
|
||||
timezone === 'Local'
|
||||
? expiration
|
||||
: expiration
|
||||
? new Date(expiration.getTime() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<button
|
||||
className="px-4 py-2 font-bold text-white bg-stargaze rounded-md"
|
||||
onClick={() => {
|
||||
void handleSendMessage()
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
{authMode === 'Grant' ? 'Grant Authorization' : 'Revoke Authorization'}
|
||||
</button>
|
||||
{transactionHash && (
|
||||
<Alert className="justify-center items-center space-y-2 w-3/4" type="info">
|
||||
{`Transaction Hash: ${transactionHash}`}
|
||||
</Alert>
|
||||
)}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export default withMetadata(Grant, { center: false })
|
1
pages/authz/index.tsx
Normal file
1
pages/authz/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './grant'
|
120
pages/authz/revoke.tsx
Normal file
120
pages/authz/revoke.tsx
Normal file
@ -0,0 +1,120 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { GasPrice, SigningStargateClient } from '@cosmjs/stargate'
|
||||
import { Alert } from 'components/Alert'
|
||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||
import { TextInput } from 'components/forms/FormInput'
|
||||
import { useInputState } from 'components/forms/FormInput.hooks'
|
||||
import { LinkTabs } from 'components/LinkTabs'
|
||||
import { authzLinkTabs } from 'components/LinkTabs.data'
|
||||
import { getConfig } from 'config'
|
||||
import type { NextPage } from 'next'
|
||||
import { NextSeo } from 'next-seo'
|
||||
import { useState } from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import { NETWORK } from 'utils/constants'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
const RevokeAuthorization: NextPage = () => {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [transactionHash, setTransactionHash] = useState<string | undefined>(undefined)
|
||||
|
||||
const granteeAddressState = useInputState({
|
||||
id: 'grantee-address',
|
||||
name: 'granteeAddress',
|
||||
title: 'Grantee Address',
|
||||
subtitle: 'Address to revoke message authorization',
|
||||
placeholder: 'stars1...',
|
||||
})
|
||||
|
||||
const messageState = useInputState({
|
||||
id: 'message',
|
||||
name: 'message',
|
||||
title: 'Message',
|
||||
subtitle: 'Message to revoke authorization for',
|
||||
placeholder: '/cosmos.bank.v1beta1.MsgSend',
|
||||
defaultValue: '/cosmos.bank.v1beta1.MsgSend',
|
||||
})
|
||||
|
||||
const revokeAuthorization = async (granteeAddress: string, msg: string) => {
|
||||
console.log('Wallet Address: ', wallet.address)
|
||||
try {
|
||||
if (!wallet.isWalletConnected) throw new Error('Wallet not connected.')
|
||||
setTransactionHash(undefined)
|
||||
const offlineSigner = wallet.getOfflineSignerDirect()
|
||||
const stargateClient = await SigningStargateClient.connectWithSigner(getConfig(NETWORK).rpcUrl, offlineSigner, {
|
||||
gasPrice: GasPrice.fromString('0.25ustars'),
|
||||
})
|
||||
|
||||
const result = await stargateClient.signAndBroadcast(
|
||||
wallet.address || '',
|
||||
[
|
||||
{
|
||||
typeUrl: '/cosmos.authz.v1beta1.MsgRevoke',
|
||||
value: {
|
||||
granter: wallet.address,
|
||||
grantee: granteeAddress,
|
||||
msgTypeUrl: msg,
|
||||
},
|
||||
},
|
||||
],
|
||||
{
|
||||
amount: [{ amount: '500000', denom: 'ustars' }],
|
||||
gas: '200000',
|
||||
},
|
||||
)
|
||||
setTransactionHash(result.transactionHash)
|
||||
toast.success(`Revoke authorization success.`, { style: { maxWidth: 'none' } })
|
||||
} catch (e: any) {
|
||||
console.log(e)
|
||||
setTransactionHash(undefined)
|
||||
toast.error(e.message, { style: { maxWidth: 'none' } })
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="px-4 pt-4 pb-16 mx-auto ml-8 space-y-8 w-full">
|
||||
<NextSeo title="Authorization" />
|
||||
<ContractPageHeader
|
||||
description="Here you can grant and revoke authorizations."
|
||||
link="https://docs.stargaze.zone/developers/authz"
|
||||
title="Authorization"
|
||||
/>
|
||||
<LinkTabs activeIndex={1} data={authzLinkTabs} />
|
||||
<div className="flex flex-col w-1/3">
|
||||
<span className="font-bold text-white">Authorization Type</span>
|
||||
<select
|
||||
className="py-2 px-4 mt-2 bg-black rounded-md border-2 border-white"
|
||||
onChange={(e) => messageState.onChange(e.target.value)}
|
||||
>
|
||||
<option className="bg-black" value="/cosmos.bank.v1beta1.MsgSend">
|
||||
/cosmos.bank.v1beta1.MsgSend
|
||||
</option>
|
||||
<option className="bg-black" value="/cosmos.staking.v1beta1.MsgDelegate">
|
||||
/cosmos.staking.v1beta1.MsgDelegate
|
||||
</option>
|
||||
<option className="bg-black" value="/cosmos.staking.v1beta1.MsgUndelegate">
|
||||
/cosmos.staking.v1beta1.MsgUndelegate
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<TextInput className="w-1/3" {...granteeAddressState} />
|
||||
{/* <TextInput className="w-1/3" {...messageState} /> */}
|
||||
<button
|
||||
className="text-white bg-stargaze btn"
|
||||
onClick={() => void revokeAuthorization(granteeAddressState.value, messageState.value)}
|
||||
type="button"
|
||||
>
|
||||
Revoke Authorization
|
||||
</button>
|
||||
{transactionHash && (
|
||||
<Alert className="justify-center items-center space-y-2 w-3/4" type="info">
|
||||
{`Transaction Hash: ${transactionHash}`}
|
||||
</Alert>
|
||||
)}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
export default withMetadata(RevokeAuthorization, { center: false })
|
@ -1,97 +0,0 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { coins } from '@cosmjs/proto-signing'
|
||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||
import { TextInput } from 'components/forms/FormInput'
|
||||
import { useInputState } from 'components/forms/FormInput.hooks'
|
||||
import type { NextPage } from 'next'
|
||||
import { NextSeo } from 'next-seo'
|
||||
import { useState } from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { links } from 'utils/links'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
const RevokeAuthorization: NextPage = () => {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [transactionHash, setTransactionHash] = useState<string | undefined>(undefined)
|
||||
|
||||
const granteeAddressState = useInputState({
|
||||
id: 'grantee-address',
|
||||
name: 'granteeAddress',
|
||||
title: 'Grantee Address',
|
||||
subtitle: 'Address to revoke message authorization',
|
||||
placeholder: 'stars1234567890abcdefghijklmnopqrstuvwxyz...',
|
||||
defaultValue: 'stars12vfpmlvmqrh9p0kcrtv6lw9ylkh7reuczdmmz5',
|
||||
})
|
||||
|
||||
const messageState = useInputState({
|
||||
id: 'message',
|
||||
name: 'message',
|
||||
title: 'Message',
|
||||
subtitle: 'Message to revoke authorization for',
|
||||
placeholder: '/cosmos.bank.v1beta1.MsgSend',
|
||||
defaultValue: '/cosmos.bank.v1beta1.MsgSend',
|
||||
})
|
||||
|
||||
const revokeAuthorization = async (granteeAddress: string, msg: string) => {
|
||||
console.log('Wallet Address: ', wallet.address)
|
||||
try {
|
||||
if (!wallet.isWalletConnected) throw new Error('Wallet not connected.')
|
||||
const result = await (
|
||||
await wallet.getSigningCosmWasmClient()
|
||||
).signAndBroadcast(
|
||||
wallet.address || '',
|
||||
[
|
||||
{
|
||||
typeUrl: '/cosmos.authz.v1beta1.MsgRevoke',
|
||||
value: {
|
||||
granter: wallet.address,
|
||||
grantee: granteeAddress,
|
||||
msgTypeUrl: msg,
|
||||
funds: coins('100000', 'ustars'),
|
||||
},
|
||||
},
|
||||
],
|
||||
'auto',
|
||||
)
|
||||
setTransactionHash(result.transactionHash)
|
||||
} catch (e: any) {
|
||||
console.log(e)
|
||||
toast.error(e.message, { style: { maxWidth: 'none' } })
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="py-6 px-12 space-y-4">
|
||||
<NextSeo title="Revoke Authorization" />
|
||||
<ContractPageHeader description="Revoke Authorization." link={links.Documentation} title="Revoke Authorization" />
|
||||
<TextInput {...granteeAddressState} />
|
||||
<div className="font-bold">Message Types</div>
|
||||
<select
|
||||
className="py-2 px-4 bg-black border-2 border-white"
|
||||
onChange={(e) => messageState.onChange(e.target.value)}
|
||||
>
|
||||
<option className="bg-black" value="/cosmos.bank.v1beta1.MsgSend">
|
||||
/cosmos.bank.v1beta1.MsgSend
|
||||
</option>
|
||||
<option className="bg-black" value="/cosmos.staking.v1beta1.MsgUndelegate">
|
||||
/cosmos.staking.v1beta1.MsgUndelegate
|
||||
</option>
|
||||
</select>
|
||||
<TextInput {...messageState} />
|
||||
<button
|
||||
className="text-white bg-stargaze btn"
|
||||
onClick={() => void revokeAuthorization(granteeAddressState.value, messageState.value)}
|
||||
type="button"
|
||||
>
|
||||
Revoke Authorization
|
||||
</button>
|
||||
{transactionHash && (
|
||||
<div className="justify-center items-center space-y-2">{`Transaction Hash: ${transactionHash}`}</div>
|
||||
)}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
export default withMetadata(RevokeAuthorization, { center: false })
|
@ -4727,6 +4727,11 @@ cosmiconfig@^7.0.1:
|
||||
path-type "^4.0.0"
|
||||
yaml "^1.10.0"
|
||||
|
||||
cosmjs-types@0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.9.0.tgz#c3bc482d28c7dfa25d1445093fdb2d9da1f6cfcc"
|
||||
integrity sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==
|
||||
|
||||
cosmjs-types@^0.4.0:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.4.1.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user