Skip to content

Commit

Permalink
TypedData supported and tested
Browse files Browse the repository at this point in the history
  • Loading branch information
Ptroger committed Jan 29, 2024
1 parent bfd683d commit 87c85b0
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -239,18 +239,88 @@ describe('decode', () => {
})
})
})
// describe('message and typed data input', () => {
// it('decodes message', () => {
// });
// it('decodes typed data', () => {
// });
// it('decodes raw message', () => {
// });
// it('decodes permit', () => {
// });
// it('decodes permit2', () => {
// });
// it('defaults to raw payload', () => {
// });
// });
describe('message and typed data input', () => {
it('decodes message', () => {})
it('decodes typed data', () => {
const decoded = decoder.decode({
type: InputType.TYPED_DATA,
typedData: {
chainId: 137,
from: '0xEd123cf8e3bA51c6C15DA1eAc74B2b5DEEA31448',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
],
DoStuff: [
{ name: 'do', type: 'function' },
{ name: 'stuff', type: 'address' }
]
},
primaryType: 'DoStuff',
domain: {
name: 'Unicorn Milk Token',
version: '0.1.0',
chainId: 137,
verifyingContract: '0x64060aB139Feaae7f06Ca4E63189D86aDEb51691'
},
message: {
do: 'doingStuff(address stuff)',
stuff: '0x1234567890123456789012345678901234567890'
}
}
})
expect(decoded).toEqual({
from: 'eip155:137/0xed123cf8e3ba51c6c15da1eac74b2b5deea31448',
type: Intents.SIGN_TYPED_DATA,
domain: {
version: '0.1.0',
name: 'Unicorn Milk Token',
chainId: 137,
verifyingContract: '0x64060aB139Feaae7f06Ca4E63189D86aDEb51691'
}
})
})
it('decodes raw message', () => {})
it('decodes permit', () => {
// const permit = {
// }
})
it('decodes permit2', () => {
// const permit2 = {
// types: {
// EIP712Domain: [
// {name: 'name', 'type': 'string'},
// {name: 'version', 'type': 'string'},
// {name: 'chainId', 'type': 'uint256'},
// {name: 'verifyingContract', 'type': 'address'}
// ],
// Permit2: [
// {name: 'holder', 'type': 'address'},
// {name: 'spender', 'type': 'address'},
// {name: 'nonce', 'type': 'uint256'},
// {name: 'expiry', 'type': 'uint256'},
// {name: 'value', 'type': 'uint256'}
// ]
// },
// primaryType: 'Permit2',
// domain: {
// name: 'UNI Token',
// version: '1',
// chainId: 1,
// verifyingContract: '0x000000000022D473030F116dDEE9F6B43aC78BA3'
// },
// message: {
// holder: '0xAliceAddress',
// spender: '0xSpenderAddress',
// nonce: 0,
// expiry: 1714521600, // Example UNIX timestamp (e.g., 1st May 2022)
// value: 10000000000000000000 // Example value in wei
// }
// }
})
it('defaults to raw payload', () => {})
})
})
19 changes: 16 additions & 3 deletions packages/transaction-request-intent/src/lib/decoders/Decoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import {
TransactionCategory,
TransactionInput,
TransactionRegistry,
TransactionStatus
TransactionStatus,
TypedDataInput
} from '../domain'
import { TransactionRequestIntentError } from '../error'
import { Intent } from '../intent.types'
import { Intent, TypedDataIntent } from '../intent.types'
import { isSupportedMethodId } from '../typeguards'
import { getCategory, getMethodId, getTransactionIntentType, transactionLookup } from '../utils'
import { decodeTypedData, getCategory, getMethodId, getTransactionIntentType, transactionLookup } from '../utils'
import {
validateContractDeploymentInput,
validateContractInteractionInput,
Expand Down Expand Up @@ -106,13 +107,25 @@ export default class Decoder {
})
}

decodeTypedData(input: TypedDataInput): TypedDataIntent {
const { typedData } = input
const { primaryType } = typedData
switch (primaryType) {
default:
return decodeTypedData(typedData)
}
}

public decode(input: DecodeInput): Intent {
switch (input.type) {
case InputType.TRANSACTION_REQUEST: {
const strategy = this.#findTransactionStrategy(input)
const decoded = strategy.decode()
return this.#wrapTransactionManagementIntents(decoded, input)
}
case InputType.TYPED_DATA: {
return this.decodeTypedData(input)
}
default:
throw new Error('Invalid input type')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default abstract class DecoderStrategy {
const method = this.getMethod(methodId)
try {
const params = decodeAbiParameters(method.abi, data)
console.log('params', params)
return method.transformer(params)
} catch (error) {
throw new Error(`Failed to decode abi parameters: ${error}`)
Expand Down
15 changes: 11 additions & 4 deletions packages/transaction-request-intent/src/lib/domain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AccountId, Address, Alg, AssetType, Hex, TransactionRequest } from '@narval/authz-shared'
import { TypedDataDomain, TypedData as TypedDataParams } from 'viem'
import { TypedData as TypedDataParams } from 'viem'
import { Intent } from './intent.types'

export type Message = {
Expand All @@ -8,17 +8,24 @@ export type Message = {
from: Address
}

export type Eip712Domain = {
version: string
chainId: number
name: string
verifyingContract: Address
}

export type Raw = {
rawData: string
algorithm: Alg
}

export type TypedData = {
chainId: string
from: Address
chainId: number
types: TypedDataParams
primaryType: string
domain: TypedDataDomain
domain: Eip712Domain
message: Record<string, unknown>
}

Expand Down Expand Up @@ -167,5 +174,5 @@ export enum Slip44SupportedAddresses {
ETH = 60,
MATIC = 966
}
export const permit2Address = '0x000000000022d473030f116ddee9f6b43ac78ba3'
export const PERMIT2_ADDRESS = '0x000000000022d473030f116ddee9f6b43ac78ba3'
export const NULL_METHOD_ID = '0x00000000'
6 changes: 4 additions & 2 deletions packages/transaction-request-intent/src/lib/intent.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AccountId, Alg, AssetId, Hex } from '@narval/authz-shared'
import { Address, TypedData } from 'viem'
import { Address } from 'viem'
import { Intents } from './domain'

export type TransferNative = {
Expand Down Expand Up @@ -69,7 +69,7 @@ export type SignRawPayload = {
export type SignTypedData = {
type: Intents.SIGN_TYPED_DATA
from: AccountId
typedData: TypedData
domain: Eip712Domain

Check failure on line 72 in packages/transaction-request-intent/src/lib/intent.types.ts

View workflow job for this annotation

GitHub Actions / Build and test

Cannot find name 'Eip712Domain'.

Check failure on line 72 in packages/transaction-request-intent/src/lib/intent.types.ts

View workflow job for this annotation

GitHub Actions / Build and test

Cannot find name 'Eip712Domain'.
}

export type DeployContract = {
Expand Down Expand Up @@ -131,6 +131,8 @@ export type UserOperation = {
beneficiary: Address
}

export type TypedDataIntent = SignTypedData | Permit | Permit2

export type Intent =
| TransferNative
| TransferErc20
Expand Down
38 changes: 38 additions & 0 deletions packages/transaction-request-intent/src/lib/supported-methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,41 @@ export const SUPPORTED_METHODS: MethodsMapping = {
intent: Intents.TRANSFER_NATIVE
}
}

export const permitTypedData = {
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
],
Permit: [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
]
},
primaryType: 'Permit' as const
}

export const permit2TypedData = {
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
],
Permit: [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
]
},
primaryType: 'Permit' as const
}
24 changes: 24 additions & 0 deletions packages/transaction-request-intent/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import {
TransactionKey,
TransactionRegistry,
TransactionStatus,
TypedData,
WalletType
} from './domain'
import { SignTypedData } from './intent.types'
import { SUPPORTED_METHODS, SupportedMethodId } from './supported-methods'
import { assertLowerHexString, isAssetType, isString, isSupportedMethodId } from './typeguards'

Expand Down Expand Up @@ -137,6 +139,28 @@ export const buildTransactionRegistry = (input: TransactionRegistryInput): Trans
return registry
}

export const decodeTypedData = (typedData: TypedData): SignTypedData => ({
type: Intents.SIGN_TYPED_DATA,
domain: typedData.domain,
from: toAccountId({
chainId: typedData.domain.chainId,
address: typedData.from.toLowerCase() as Address
})
})

export const decodePermit = (typedData: TypedData): SignTypedData => {
const { domain } = typedData
// const { spender, value, nonce, deadline } = message
return {
type: Intents.SIGN_TYPED_DATA,
domain,
from: toAccountId({
chainId: domain.chainId,
address: typedData.from
})
}
}

export const transactionLookup = (
txRequest: TransactionRequest,
transactionRegistry?: TransactionRegistry
Expand Down

0 comments on commit 87c85b0

Please sign in to comment.