Skip to content

Commit

Permalink
refactor: using only viem for EIP712 (#1516)
Browse files Browse the repository at this point in the history
* refactor: using viem for eip721

* refactor: using viem for eip721

* refactor: using viem for eip721

* refactor: using viem for eip721

* refactor: using viem for eip721

* refactor: using viem for eip721

* refactor: using viem for eip721

* fix: new slack version
  • Loading branch information
freemanzMrojo authored Nov 18, 2024
1 parent 9d772cd commit 0032395
Show file tree
Hide file tree
Showing 17 changed files with 80 additions and 58 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/unit-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ jobs:
if: always() && github.ref == 'refs/heads/main' && (steps.unit-test.outcome == 'failure')
uses: slackapi/slack-github-action@v2.0.0
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: webhook-trigger
payload: |
{
"source": "GitHub",
"repo": "${{ github.repository}}",
"branch": "${{ github.head_ref || github.ref_name }}",
"message": "unit tests failed, see run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
THOR_SOLO_URL,
ThorClient,
VeChainProvider
} from '@vechain/sdk-network'; // START_SNIPPET: FullFlowDelegatorPrivateKeySnippet
} from '@vechain/sdk-network';
import { expect } from 'expect';

// START_SNIPPET: FullFlowDelegatorPrivateKeySnippet
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/transactions/full-flow-delegator-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
TESTNET_URL,
ThorClient,
VeChainProvider
} from '@vechain/sdk-network'; // START_SNIPPET: FullFlowDelegatorUrlSnippet
} from '@vechain/sdk-network';
import { expect } from 'expect';

// START_SNIPPET: FullFlowDelegatorUrlSnippet
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/transactions/full-flow-no-delegator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
THOR_SOLO_URL,
ThorClient,
VeChainProvider
} from '@vechain/sdk-network'; // START_SNIPPET: FullFlowNoDelegatorSnippet
} from '@vechain/sdk-network';
import { expect } from 'expect';

// START_SNIPPET: FullFlowNoDelegatorSnippet
Expand Down
12 changes: 0 additions & 12 deletions docs/transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,6 @@ In the following complete examples, we will explore the entire lifecycle of a Ve
1. **No Delegation (Signing Only with an Origin Private Key)**: In this scenario, we'll demonstrate the basic process of creating a transaction, signing it with the origin private key, and sending it to the VeChainThor blockchain without involving fee delegation.

```typescript { name=full-flow-no-delegator, category=example }
import { expect } from 'expect';

// START_SNIPPET: FullFlowNoDelegatorSnippet

// 1 - Create the thor client
const thorSoloClient = ThorClient.at(THOR_SOLO_URL, {
isPollingEnabled: false
Expand Down Expand Up @@ -456,10 +452,6 @@ const txReceipt = await thorSoloClient.transactions.waitForTransaction(
2. **Delegation with Private Key**: Here, we'll extend the previous example by incorporating fee delegation. The transaction sender will delegate the transaction fee payment to another entity (delegator), and we'll guide you through the steps of building, signing, and sending such a transaction.

```typescript { name=full-flow-delegator-private-key, category=example }
import { expect } from 'expect';

// START_SNIPPET: FullFlowDelegatorPrivateKeySnippet

// 1 - Create the thor client
const thorSoloClient = ThorClient.at(THOR_SOLO_URL, {
isPollingEnabled: false
Expand Down Expand Up @@ -561,10 +553,6 @@ const txReceipt = await thorSoloClient.transactions.waitForTransaction(
3. **Delegation with URL**: This example will showcase the use of a delegation URL for fee delegation. The sender will specify a delegation URL in the `signTransaction` options, allowing a designated sponsor to pay the transaction fee. We'll cover the full process, from building clauses to verifying the transaction on-chain.

```typescript { name=full-flow-delegator-url, category=example }
import { expect } from 'expect';

// START_SNIPPET: FullFlowDelegatorUrlSnippet

// 1 - Create the thor client
const thorClient = ThorClient.at(TESTNET_URL, {
isPollingEnabled: false
Expand Down
3 changes: 1 addition & 2 deletions packages/aws-kms-adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"@vechain/sdk-errors": "1.0.0-rc.2",
"@vechain/sdk-network": "1.0.0-rc.2",
"asn1js": "^3.0.5",
"ethers": "6.13.4",
"viem": "^2.21.19"
"viem": "^2.21.45"
}
}
18 changes: 10 additions & 8 deletions packages/aws-kms-adapter/src/KMSVeChainSigner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
} from '@vechain/sdk-network';
import { BitString, ObjectIdentifier, Sequence, verifySchema } from 'asn1js';
import {
hashTypedData,
recoverPublicKey,
toHex,
type TypedDataDomain,
TypedDataEncoder,
type TypedDataField
} from 'ethers';
import { recoverPublicKey, toHex } from 'viem';
type TypedDataParameter
} from 'viem';
import { KMSVeChainProvider } from './KMSVeChainProvider';

class KMSVeChainSigner extends VeChainAbstractSigner {
Expand Down Expand Up @@ -388,20 +389,21 @@ class KMSVeChainSigner extends VeChainAbstractSigner {
*/
public async signTypedData(
domain: TypedDataDomain,
types: Record<string, TypedDataField[]>,
value: Record<string, unknown>
types: Record<string, TypedDataParameter[]>,
primaryType: string,
message: Record<string, unknown>
): Promise<string> {
try {
const payload = Hex.of(
TypedDataEncoder.hash(domain, types, value)
hashTypedData({ domain, types, primaryType, message })
).bytes;

return await this.signPayload(payload);
} catch (error) {
throw new SignerMethodError(
'KMSVeChainSigner.signTypedData',
'The typed data could not be signed.',
{ domain, types, value },
{ domain, types, primaryType, message },
error
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ describe('KMSVeChainSigner - Thor Solo', () => {
const signature = await signer.signTypedData(
typedData.domain,
typedData.types,
typedData.primaryType,
typedData.data
);
expect(signature).toBeDefined();
Expand Down
6 changes: 4 additions & 2 deletions packages/aws-kms-adapter/tests/KMSVeChainSigner.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
type ThorClient,
type TransactionRequestInput
} from '@vechain/sdk-network';
import { type TypedDataDomain, type TypedDataField } from 'ethers';
import { type TypedDataDomain, type TypedDataParameter } from 'viem';
import { KMSVeChainProvider, KMSVeChainSigner } from '../src';
import { EIP712_CONTRACT, EIP712_FROM, EIP712_TO } from './fixture';
jest.mock('asn1js', () => ({
Expand Down Expand Up @@ -136,6 +136,7 @@ describe('KMSVeChainSigner', () => {
}
]
},
'Mail',
{
from: {
name: 'Cow',
Expand All @@ -159,7 +160,8 @@ describe('KMSVeChainSigner', () => {
await expect(
signer.signTypedData(
{} as unknown as TypedDataDomain,
{} as unknown as Record<string, TypedDataField[]>,
{} as unknown as Record<string, TypedDataParameter[]>,
'primaryType',
{} as unknown as Record<string, unknown>
)
).rejects.toThrow(SignerMethodError);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"abitype": "^1.0.6",
"ethers": "6.13.4",
"fast-json-stable-stringify": "^2.1.0",
"viem": "^2.21.19"
"viem": "^2.21.45"
},
"devDependencies": {
"bignumber.js": "^9.1.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/network/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"abitype": "^1.0.6",
"ethers": "6.13.4",
"isomorphic-ws": "^5.0.0",
"viem": "^2.21.19",
"viem": "^2.21.45",
"ws": "^8.18.0"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
JSONRPCInvalidParams,
stringifyData
} from '@vechain/sdk-errors';
import type { TypedDataDomain, TypedDataField } from 'ethers';
import type { TypedDataDomain, TypedDataParameter } from 'viem';
import type { VeChainSigner } from '../../../../../signer/signers';
import type { ThorClient } from '../../../../../thor-client';
import type { VeChainProvider } from '../../../../providers/vechain-provider';
Expand Down Expand Up @@ -61,7 +61,7 @@ const ethSignTypedDataV4 = async (
{
primaryType: string;
domain: TypedDataDomain;
types: Record<string, TypedDataField[]>;
types: Record<string, TypedDataParameter[]>;
message: Record<string, unknown>;
}
];
Expand All @@ -74,6 +74,7 @@ const ethSignTypedDataV4 = async (
return await signer.signTypedData(
typedData.domain,
typedData.types,
typedData.primaryType,
typedData.message
);
} catch (error) {
Expand Down
8 changes: 5 additions & 3 deletions packages/network/src/signer/signers/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
type HardhatVeChainProvider,
type VeChainProvider
} from '../../provider';
import { type TypedDataDomain, type TypedDataParameter } from 'viem';

/**
* Available types for the VeChainProvider's
Expand Down Expand Up @@ -358,9 +359,10 @@ interface VeChainSigner {
* Signs the [[link-eip-712]] typed data.
*/
signTypedData: (
domain: vechain_sdk_core_ethers.TypedDataDomain,
types: Record<string, vechain_sdk_core_ethers.TypedDataField[]>,
value: Record<string, unknown>,
domain: TypedDataDomain,
types: Record<string, TypedDataParameter[]>,
primaryType: string,
message: Record<string, unknown>,
options?: SignTypedDataOptions
) => Promise<string>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
type TransactionClause
} from '@vechain/sdk-core';
import { InvalidDataType, JSONRPCInvalidParams } from '@vechain/sdk-errors';
import { type TypedDataDomain, type TypedDataField } from 'ethers';
import { type TypedDataDomain, type TypedDataParameter } from 'viem';
import { RPC_METHODS } from '../../../provider/utils/const/rpc-mapper/rpc-methods';
import { type TransactionSimulationResult } from '../../../thor-client';
import { vnsUtils } from '../../../utils';
Expand Down Expand Up @@ -336,15 +336,17 @@ abstract class VeChainAbstractSigner implements VeChainSigner {
* Signs the [[link-eip-712]] typed data.
*
* @param {TypedDataDomain} domain - The domain parameters used for signing.
* @param {Record<string, TypedDataField[]>} types - The types used for signing.
* @param {Record<string, unknown>} value - The message data to be signed.
* @param {Record<string, TypedDataParameter[]>} types - The types used for signing.
* @param {string} primaryType - The primary type used for signing.
* @param {Record<string, unknown>} message - The message data to be signed.
*
* @return {Promise<string>} - A promise that resolves with the signature string.
*/
abstract signTypedData(
domain: TypedDataDomain,
types: Record<string, TypedDataField[]>,
value: Record<string, unknown>,
types: Record<string, TypedDataParameter[]>,
primaryType: string,
message: Record<string, unknown>,
options?: SignTypedDataOptions
): Promise<string>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
stringifyData
} from '@vechain/sdk-errors';
import {
hashTypedData,
type TypedDataDomain,
TypedDataEncoder,
type TypedDataField
} from 'ethers';
type TypedDataParameter
} from 'viem';
import { RPC_METHODS } from '../../../provider/utils/const/rpc-mapper/rpc-methods';
import {
DelegationHandler,
Expand Down Expand Up @@ -198,20 +198,22 @@ class VeChainPrivateKeySigner extends VeChainAbstractSigner {
* albeit Ethereum Name Services are not resolved because he resolution depends on **ethers** provider implementation.
*
* @param {TypedDataDomain} domain - The domain parameters used for signing.
* @param {Record<string, TypedDataField[]>} types - The types used for signing.
* @param {Record<string, unknown>} value - The value data to be signed.
* @param {Record<string, TypedDataParameter[]>} types - The types used for signing.
* @param {string} primaryType - The primary type used for signing.
* @param {Record<string, unknown>} message - The value data to be signed.
*
* @return {Promise<string>} - A promise that resolves with the signature string.
*/
async signTypedData(
domain: TypedDataDomain,
types: Record<string, TypedDataField[]>,
value: Record<string, unknown>
types: Record<string, TypedDataParameter[]>,
primaryType: string,
message: Record<string, unknown>
): Promise<string> {
return await new Promise((resolve, reject) => {
try {
const hash = Hex.of(
TypedDataEncoder.hash(domain, types, value)
hashTypedData({ domain, types, primaryType, message })
).bytes;
const sign = Secp256k1.sign(
hash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
populateCallTestCases,
populateCallTestCasesAccount
} from './fixture';
import { InvalidAbiEncodingTypeError } from 'viem';

/**
* VeChain base signer tests
Expand Down Expand Up @@ -290,9 +291,10 @@ describe('VeChain base signer tests', () => {
signer.signTypedData(
eip712TestCases.invalid.domain,
eip712TestCases.invalid.types,
eip712TestCases.invalid.primaryType,
eip712TestCases.invalid.data
)
).rejects.toThrowError(TypeError);
).rejects.toThrowError(InvalidAbiEncodingTypeError);
});

test('signTypedData - exception when parsing to hex', async () => {
Expand All @@ -313,6 +315,7 @@ describe('VeChain base signer tests', () => {
signer.signTypedData(
eip712TestCases.valid.domain,
eip712TestCases.valid.types,
eip712TestCases.valid.primaryType,
eip712TestCases.valid.data
)
).rejects.toThrowError(expectedErrorString);
Expand All @@ -321,6 +324,7 @@ describe('VeChain base signer tests', () => {
signer.signTypedData(
eip712TestCases.valid.domain,
eip712TestCases.valid.types,
eip712TestCases.valid.primaryType,
eip712TestCases.valid.data
)
).rejects.toThrowError('Error while signing typed data');
Expand All @@ -341,6 +345,7 @@ describe('VeChain base signer tests', () => {
).signTypedData(
eip712TestCases.valid.domain,
eip712TestCases.valid.types,
eip712TestCases.valid.primaryType,
eip712TestCases.valid.data
);
expect(actual).toBe(expected);
Expand Down
Loading

1 comment on commit 0032395

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

Summary

Lines Statements Branches Functions
Coverage: 99%
98.99% (4342/4386) 97.53% (1387/1422) 99% (896/905)
Title Tests Skipped Failures Errors Time
core 827 0 πŸ’€ 0 ❌ 0 πŸ”₯ 2m 18s ⏱️
network 719 0 πŸ’€ 0 ❌ 0 πŸ”₯ 4m 49s ⏱️
errors 42 0 πŸ’€ 0 ❌ 0 πŸ”₯ 17.725s ⏱️
logging 3 0 πŸ’€ 0 ❌ 0 πŸ”₯ 18.353s ⏱️
hardhat-plugin 19 0 πŸ’€ 0 ❌ 0 πŸ”₯ 57.642s ⏱️
aws-kms-adapter 23 0 πŸ’€ 0 ❌ 0 πŸ”₯ 1m 23s ⏱️
ethers-adapter 5 0 πŸ’€ 0 ❌ 0 πŸ”₯ 1m 11s ⏱️
rpc-proxy 37 0 πŸ’€ 0 ❌ 0 πŸ”₯ 1m 2s ⏱️

Please sign in to comment.