feat: add near_signMessage method to NEAR (#310)
Co-authored-by: Ben Kremer <contact@bkrem.dev>
This commit is contained in:
parent
653b362e5c
commit
cd811a6a51
3
.gitignore
vendored
3
.gitignore
vendored
@ -35,3 +35,6 @@ yarn-error.log*
|
|||||||
|
|
||||||
# vercel
|
# vercel
|
||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
|
# webstorm ide
|
||||||
|
.idea
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
"@taquito/signer": "^15.1.0",
|
"@taquito/signer": "^15.1.0",
|
||||||
"@taquito/taquito": "^15.1.0",
|
"@taquito/taquito": "^15.1.0",
|
||||||
"@walletconnect/web3wallet": "1.9.1",
|
"@walletconnect/web3wallet": "1.9.1",
|
||||||
|
"borsh": "^1.0.0",
|
||||||
"bs58": "5.0.0",
|
"bs58": "5.0.0",
|
||||||
"cosmos-wallet": "1.2.0",
|
"cosmos-wallet": "1.2.0",
|
||||||
"ethers": "5.7.2",
|
"ethers": "5.7.2",
|
||||||
|
@ -52,5 +52,6 @@ export const NEAR_SIGNING_METHODS = {
|
|||||||
NEAR_SIGN_AND_SEND_TRANSACTION: 'near_signAndSendTransaction',
|
NEAR_SIGN_AND_SEND_TRANSACTION: 'near_signAndSendTransaction',
|
||||||
NEAR_SIGN_TRANSACTIONS: 'near_signTransactions',
|
NEAR_SIGN_TRANSACTIONS: 'near_signTransactions',
|
||||||
NEAR_SIGN_AND_SEND_TRANSACTIONS: 'near_signAndSendTransactions',
|
NEAR_SIGN_AND_SEND_TRANSACTIONS: 'near_signAndSendTransactions',
|
||||||
NEAR_VERIFY_OWNER: 'near_verifyOwner'
|
NEAR_VERIFY_OWNER: 'near_verifyOwner',
|
||||||
|
NEAR_SIGN_MESSAGE: 'near_signMessage'
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,7 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
|
|||||||
case NEAR_SIGNING_METHODS.NEAR_SIGN_TRANSACTIONS:
|
case NEAR_SIGNING_METHODS.NEAR_SIGN_TRANSACTIONS:
|
||||||
case NEAR_SIGNING_METHODS.NEAR_SIGN_AND_SEND_TRANSACTIONS:
|
case NEAR_SIGNING_METHODS.NEAR_SIGN_AND_SEND_TRANSACTIONS:
|
||||||
case NEAR_SIGNING_METHODS.NEAR_VERIFY_OWNER:
|
case NEAR_SIGNING_METHODS.NEAR_VERIFY_OWNER:
|
||||||
|
case NEAR_SIGNING_METHODS.NEAR_SIGN_MESSAGE:
|
||||||
return ModalStore.open('SessionSignNearModal', { requestEvent, requestSession })
|
return ModalStore.open('SessionSignNearModal', { requestEvent, requestSession })
|
||||||
|
|
||||||
case MULTIVERSX_SIGNING_METHODS.MULTIVERSX_SIGN_MESSAGE:
|
case MULTIVERSX_SIGNING_METHODS.MULTIVERSX_SIGN_MESSAGE:
|
||||||
|
@ -9,6 +9,7 @@ import { AccessKeyView } from 'near-api-js/lib/providers/provider'
|
|||||||
|
|
||||||
import { web3wallet } from '@/utils/WalletConnectUtil'
|
import { web3wallet } from '@/utils/WalletConnectUtil'
|
||||||
import { NEAR_TEST_CHAINS, TNearChain } from '@/data/NEARData'
|
import { NEAR_TEST_CHAINS, TNearChain } from '@/data/NEARData'
|
||||||
|
import { Schema, serialize } from 'borsh'
|
||||||
|
|
||||||
const MAX_ACCOUNTS = 2
|
const MAX_ACCOUNTS = 2
|
||||||
|
|
||||||
@ -63,6 +64,58 @@ interface SignAndSendTransactionsParams {
|
|||||||
transactions: Array<nearTransactions.Transaction>
|
transactions: Array<nearTransactions.Transaction>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SignMessageParamsNEP {
|
||||||
|
message: string
|
||||||
|
recipient: string
|
||||||
|
nonce: Buffer
|
||||||
|
callbackUrl?: string
|
||||||
|
state?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SignMessageParams {
|
||||||
|
chainId: string
|
||||||
|
messageParams: SignMessageParamsNEP & {
|
||||||
|
accountId?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SignedMessage {
|
||||||
|
accountId: string
|
||||||
|
publicKey: string
|
||||||
|
signature: string
|
||||||
|
state?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MessagePayload {
|
||||||
|
tag: number
|
||||||
|
message: string
|
||||||
|
nonce: Buffer
|
||||||
|
recipient: string
|
||||||
|
callbackUrl?: string
|
||||||
|
|
||||||
|
constructor(data: SignMessageParamsNEP) {
|
||||||
|
// The tag's value is a hardcoded value as per
|
||||||
|
// defined in the NEP [NEP413](https://github.com/near/NEPs/blob/master/neps/nep-0413.md)
|
||||||
|
this.tag = 2147484061
|
||||||
|
this.message = data.message
|
||||||
|
this.nonce = data.nonce
|
||||||
|
this.recipient = data.recipient
|
||||||
|
if (data.callbackUrl) {
|
||||||
|
this.callbackUrl = data.callbackUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const payloadSchema: Schema = {
|
||||||
|
struct: {
|
||||||
|
tag: 'u32',
|
||||||
|
message: 'string',
|
||||||
|
nonce: { array: { type: 'u8', len: 32 } },
|
||||||
|
recipient: 'string',
|
||||||
|
callbackUrl: { option: 'string' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class NearWallet {
|
export class NearWallet {
|
||||||
private networkId: string
|
private networkId: string
|
||||||
private keyStore: nearKeyStores.KeyStore
|
private keyStore: nearKeyStores.KeyStore
|
||||||
@ -342,4 +395,35 @@ export class NearWallet {
|
|||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async signMessage({ chainId, messageParams }: SignMessageParams): Promise<SignedMessage> {
|
||||||
|
const { message, nonce, recipient, callbackUrl, state, accountId } = messageParams
|
||||||
|
const nonceArray = Buffer.from(nonce)
|
||||||
|
|
||||||
|
if (nonceArray.length !== 32) {
|
||||||
|
throw Error('Expected nonce to be a 32 bytes buffer')
|
||||||
|
}
|
||||||
|
|
||||||
|
const accounts = await this.getAllAccounts()
|
||||||
|
const account = accounts.find(acc => acc.accountId === accountId)
|
||||||
|
|
||||||
|
// If no accountId is provided in params default to the first accountId in accounts.
|
||||||
|
// in a real wallet it would default to the `active/selected` account
|
||||||
|
// this is because we should be able to use `signMessage` without `signIn`.
|
||||||
|
const accId = account ? account.accountId : accounts[0].accountId
|
||||||
|
|
||||||
|
const signer = new InMemorySigner(this.getKeyStore())
|
||||||
|
const networkId = chainId.split(':')[1]
|
||||||
|
|
||||||
|
// Create the message payload and sign it
|
||||||
|
const payload = new MessagePayload({ message, nonce: nonceArray, recipient, callbackUrl })
|
||||||
|
const encodedPayload = serialize(payloadSchema, payload)
|
||||||
|
const signed = await signer.signMessage(encodedPayload, accId, networkId)
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountId: accId,
|
||||||
|
publicKey: signed.publicKey.toString(),
|
||||||
|
signature: Buffer.from(signed.signature).toString('base64')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,24 @@ export async function approveNearRequest(
|
|||||||
keyType: signed.publicKey.keyType
|
keyType: signed.publicKey.keyType
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
case NEAR_SIGNING_METHODS.NEAR_SIGN_MESSAGE: {
|
||||||
|
console.log('approve', { id, params })
|
||||||
|
|
||||||
|
if (!chainId) {
|
||||||
|
throw new Error('Invalid chain id')
|
||||||
|
}
|
||||||
|
|
||||||
|
const { accountId, publicKey, signature } = await nearWallet.signMessage({
|
||||||
|
chainId,
|
||||||
|
messageParams: params.request.params
|
||||||
|
})
|
||||||
|
|
||||||
|
return formatJsonRpcResult(id, {
|
||||||
|
accountId,
|
||||||
|
publicKey,
|
||||||
|
signature
|
||||||
|
})
|
||||||
|
}
|
||||||
case NEAR_SIGNING_METHODS.NEAR_SIGN_AND_SEND_TRANSACTIONS: {
|
case NEAR_SIGNING_METHODS.NEAR_SIGN_AND_SEND_TRANSACTIONS: {
|
||||||
console.log('approve', { id, params })
|
console.log('approve', { id, params })
|
||||||
|
|
||||||
|
@ -3189,6 +3189,11 @@ borsh@^0.7.0:
|
|||||||
bs58 "^4.0.0"
|
bs58 "^4.0.0"
|
||||||
text-encoding-utf-8 "^1.0.2"
|
text-encoding-utf-8 "^1.0.2"
|
||||||
|
|
||||||
|
borsh@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/borsh/-/borsh-1.0.0.tgz#b564c8cc8f7a91e3772b9aef9e07f62b84213c1f"
|
||||||
|
integrity sha512-fSVWzzemnyfF89EPwlUNsrS5swF5CrtiN4e+h0/lLf4dz2he4L3ndM20PS9wj7ICSkXJe/TQUHdaPTq15b1mNQ==
|
||||||
|
|
||||||
brace-expansion@^1.1.7:
|
brace-expansion@^1.1.7:
|
||||||
version "1.1.11"
|
version "1.1.11"
|
||||||
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
|
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
|
||||||
|
Loading…
Reference in New Issue
Block a user