feat: add near_signMessage method to NEAR (#310)

Co-authored-by: Ben Kremer <contact@bkrem.dev>
This commit is contained in:
kujtimprenkuSQA 2023-10-16 17:38:26 +02:00 committed by GitHub
parent 653b362e5c
commit cd811a6a51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 114 additions and 1 deletions

3
.gitignore vendored
View File

@ -35,3 +35,6 @@ yarn-error.log*
# vercel
.vercel
# webstorm ide
.idea

View File

@ -31,6 +31,7 @@
"@taquito/signer": "^15.1.0",
"@taquito/taquito": "^15.1.0",
"@walletconnect/web3wallet": "1.9.1",
"borsh": "^1.0.0",
"bs58": "5.0.0",
"cosmos-wallet": "1.2.0",
"ethers": "5.7.2",

View File

@ -52,5 +52,6 @@ export const NEAR_SIGNING_METHODS = {
NEAR_SIGN_AND_SEND_TRANSACTION: 'near_signAndSendTransaction',
NEAR_SIGN_TRANSACTIONS: 'near_signTransactions',
NEAR_SIGN_AND_SEND_TRANSACTIONS: 'near_signAndSendTransactions',
NEAR_VERIFY_OWNER: 'near_verifyOwner'
NEAR_VERIFY_OWNER: 'near_verifyOwner',
NEAR_SIGN_MESSAGE: 'near_signMessage'
}

View File

@ -79,6 +79,7 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
case NEAR_SIGNING_METHODS.NEAR_SIGN_TRANSACTIONS:
case NEAR_SIGNING_METHODS.NEAR_SIGN_AND_SEND_TRANSACTIONS:
case NEAR_SIGNING_METHODS.NEAR_VERIFY_OWNER:
case NEAR_SIGNING_METHODS.NEAR_SIGN_MESSAGE:
return ModalStore.open('SessionSignNearModal', { requestEvent, requestSession })
case MULTIVERSX_SIGNING_METHODS.MULTIVERSX_SIGN_MESSAGE:

View File

@ -9,6 +9,7 @@ import { AccessKeyView } from 'near-api-js/lib/providers/provider'
import { web3wallet } from '@/utils/WalletConnectUtil'
import { NEAR_TEST_CHAINS, TNearChain } from '@/data/NEARData'
import { Schema, serialize } from 'borsh'
const MAX_ACCOUNTS = 2
@ -63,6 +64,58 @@ interface SignAndSendTransactionsParams {
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 {
private networkId: string
private keyStore: nearKeyStores.KeyStore
@ -342,4 +395,35 @@ export class NearWallet {
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')
}
}
}

View File

@ -162,6 +162,24 @@ export async function approveNearRequest(
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: {
console.log('approve', { id, params })

View File

@ -3189,6 +3189,11 @@ borsh@^0.7.0:
bs58 "^4.0.0"
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:
version "1.1.11"
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"