Skip to content

Commit

Permalink
wallet/adSignature: RPC to add signature to a transaction. (#5097)
Browse files Browse the repository at this point in the history
This RPC is used to add signature to a transaction. It takes a transaction and a signature as input and returns a signed transaction.
  • Loading branch information
patnir authored Jul 1, 2024
1 parent e62e36c commit 8e6dfda
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 2 deletions.
10 changes: 10 additions & 0 deletions ironfish/src/rpc/clients/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ import type {
UseAccountResponse,
} from '../routes'
import { ApiNamespace } from '../routes/namespaces'
import { AddSignatureRequest, AddSignatureResponse } from '../routes/wallet/addSignature'

export abstract class RpcClient {
abstract request<TEnd = unknown, TStream = unknown>(
Expand Down Expand Up @@ -555,6 +556,15 @@ export abstract class RpcClient {
).waitForEnd()
},

addSignature: (
params: AddSignatureRequest,
): Promise<RpcResponseEnded<AddSignatureResponse>> => {
return this.request<AddSignatureResponse>(
`${ApiNamespace.wallet}/addSignature`,
params,
).waitForEnd()
},

createTransaction: (
params: CreateTransactionRequest,
): Promise<RpcResponseEnded<CreateTransactionResponse>> => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"Route wallet/addSignature should return error if signature is not a valid hex": [
{
"value": {
"version": 4,
"id": "0e9f1f07-ee9d-4746-a4e8-131d89d71345",
"name": "addSignatureAccount2",
"spendingKey": "21557df84c37fa55363c77ffe99a6d01a1c1938f06b805b34a2d2f3442016d3c",
"viewKey": "4d8f669c3667195906dcc4e636983d653e6042267fffb3b7ed1a00e8aeacf7011382ac8e43e6f446f3751dca9640eb7d684b88c181feec8f1399863b0e389c95",
"incomingViewKey": "9f13a57239aba9daade572166257ae494807e6436a9eaaf5bf312855e225d906",
"outgoingViewKey": "5c156963119e3fbdccd84d08622eae4dbbc36ada56e30682188a338fe9be0ed6",
"publicAddress": "608569ba934ef7bb6c6bc99e653b7ab18eb17bf02602c8fc489c3286d1065f2c",
"createdAt": {
"hash": {
"type": "Buffer",
"data": "base64:R5HXrp+X3xAO8VWOhHctagm0N2I4goP3XG8goyqIqoY="
},
"sequence": 1
},
"scanningEnabled": true,
"proofAuthorizingKey": "0b3bcdc835ee3709c9a30cad80c36d0d4f5d5712349d6bbfd34da9ed405bbc02"
},
"head": {
"hash": {
"type": "Buffer",
"data": "base64:R5HXrp+X3xAO8VWOhHctagm0N2I4goP3XG8goyqIqoY="
},
"sequence": 1
}
}
]
}
36 changes: 36 additions & 0 deletions ironfish/src/rpc/routes/wallet/addSignature.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { RawTransactionSerde } from '../../../primitives'
import { useAccountFixture } from '../../../testUtilities'
import { createRawTransaction } from '../../../testUtilities/helpers/transaction'
import { createRouteTest } from '../../../testUtilities/routeTest'

describe('Route wallet/addSignature', () => {
const routeTest = createRouteTest(true)

it('should return error if signature is not a valid hex', async () => {
const account = await useAccountFixture(routeTest.node.wallet, 'addSignatureAccount')
const rawTransaction = await createRawTransaction({
wallet: routeTest.node.wallet,
from: account,
})

const response = await routeTest.client.wallet.buildTransaction({
rawTransaction: RawTransactionSerde.serialize(rawTransaction).toString('hex'),
account: account.name,
})

expect(response.status).toBe(200)
expect(response.content.unsignedTransaction).toBeDefined()

const invalidSignature = 'invalid'

await expect(
routeTest.client.wallet.addSignature({
unsignedTransaction: response.content.unsignedTransaction,
signature: invalidSignature,
}),
).rejects.toThrow('Invalid signature length')
})
})
53 changes: 53 additions & 0 deletions ironfish/src/rpc/routes/wallet/addSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { UnsignedTransaction } from '@ironfish/rust-nodejs'
import * as yup from 'yup'
import { ApiNamespace } from '../namespaces'
import { routes } from '../router'
import { AssertHasRpcContext } from '../rpcContext'

export type AddSignatureRequest = {
unsignedTransaction: string
signature: string
}

export type AddSignatureResponse = {
transaction: string
}

export const AddSignatureRequestSchema: yup.ObjectSchema<AddSignatureRequest> = yup
.object({
unsignedTransaction: yup.string().defined(),
signature: yup.string().defined(),
})
.defined()

export const AddSignatureResponseSchema: yup.ObjectSchema<AddSignatureResponse> = yup
.object({
transaction: yup.string().defined(),
})
.defined()

routes.register<typeof AddSignatureRequestSchema, AddSignatureResponse>(
`${ApiNamespace.wallet}/addSignature`,
AddSignatureRequestSchema,
(request, node): void => {
AssertHasRpcContext(request, node, 'wallet')
const unsignedTransaction = new UnsignedTransaction(
Buffer.from(request.data.unsignedTransaction, 'hex'),
)

const buffer = Buffer.from(request.data.signature, 'hex')

if (buffer.length !== 64) {
throw new Error('Invalid signature length')
}

const serialized = unsignedTransaction.addSignature(buffer)

request.end({
transaction: serialized.toString('hex'),
})
},
)
5 changes: 3 additions & 2 deletions ironfish/src/rpc/routes/wallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

export * from './setAccountHead'
export * from './addSignature'
export * from './addTransaction'
export * from './buildTransaction'
export * from './burnAsset'
Expand All @@ -12,10 +12,10 @@ export * from './createTransaction'
export * from './estimateFeeRates'
export * from './exportAccount'
export * from './getAccountNotesStream'
export * from './getAccounts'
export * from './getAccountStatus'
export * from './getAccountTransaction'
export * from './getAccountTransactions'
export * from './getAccounts'
export * from './getAccountsStatus'
export * from './getAsset'
export * from './getAssets'
Expand All @@ -38,6 +38,7 @@ export * from './renameAccount'
export * from './rescan'
export * from './resetAccount'
export * from './sendTransaction'
export * from './setAccountHead'
export * from './setScanning'
export * from './types'
export * from './use'
Expand Down

0 comments on commit 8e6dfda

Please sign in to comment.