@@ -5,12 +5,7 @@ import type { Hex } from 'ox'
55import { TxEnvelopeTempo } from 'ox/tempo'
66import { Handler } from 'tempo.ts/server'
77import { createClient , custom , encodeFunctionData , parseUnits } from 'viem'
8- import {
9- getTransaction ,
10- getTransactionReceipt ,
11- prepareTransactionRequest ,
12- signTransaction ,
13- } from 'viem/actions'
8+ import { getTransactionReceipt , prepareTransactionRequest , signTransaction } from 'viem/actions'
149import { Abis , Account , Actions , Addresses , Secp256k1 , Tick , Transaction } from 'viem/tempo'
1510import { beforeAll , describe , expect , test } from 'vp/test'
1611import * as Http from '~test/Http.js'
@@ -118,161 +113,6 @@ describe('tempo', () => {
118113 httpServer . close ( )
119114 } )
120115
121- test ( 'behavior: push mode sets validBefore no later than challenge expiry' , async ( ) => {
122- const expires = new Date ( Date . now ( ) + 60_000 ) . toISOString ( )
123- const mppx = Mppx_client . create ( {
124- polyfill : false ,
125- methods : [
126- tempo_client ( {
127- account : accounts [ 1 ] ,
128- mode : 'push' ,
129- getClient : ( ) => client ,
130- } ) ,
131- ] ,
132- } )
133-
134- const httpServer = await Http . createServer ( async ( req , res ) => {
135- const result = await Mppx_server . toNodeListener (
136- server . charge ( {
137- amount : '1' ,
138- currency : asset ,
139- expires,
140- recipient : accounts [ 0 ] . address ,
141- } ) ,
142- ) ( req , res )
143- if ( result . status === 402 ) return
144- res . end ( 'OK' )
145- } )
146-
147- const response = await mppx . fetch ( httpServer . url )
148- expect ( response . status ) . toBe ( 200 )
149-
150- const receipt = Receipt . fromResponse ( response )
151- const transaction = await getTransaction ( client , {
152- hash : receipt . reference as Hex . Hex ,
153- } )
154-
155- expect ( transaction . validBefore ) . toBeTypeOf ( 'number' )
156- expect ( transaction . validBefore ! ) . toBeLessThanOrEqual (
157- Math . floor ( new Date ( expires ) . getTime ( ) / 1000 ) ,
158- )
159-
160- httpServer . close ( )
161- } )
162-
163- test ( 'behavior: rejects hash credentials for fee-payer challenges' , async ( ) => {
164- const httpServer = await Http . createServer ( async ( req , res ) => {
165- const result = await Mppx_server . toNodeListener (
166- server . charge ( {
167- feePayer : accounts [ 0 ] ,
168- amount : '1' ,
169- currency : asset ,
170- recipient : accounts [ 0 ] . address ,
171- } ) ,
172- ) ( req , res )
173- if ( result . status === 402 ) return
174- res . end ( 'OK' )
175- } )
176-
177- const response = await fetch ( httpServer . url )
178- expect ( response . status ) . toBe ( 402 )
179-
180- const challenge = Challenge . fromResponse ( response , {
181- methods : [ tempo_client . charge ( ) ] ,
182- } )
183-
184- const { receipt } = await Actions . token . transferSync ( client , {
185- account : accounts [ 1 ] ,
186- amount : BigInt ( challenge . request . amount ) ,
187- to : challenge . request . recipient as Hex . Hex ,
188- token : challenge . request . currency as Hex . Hex ,
189- } )
190-
191- const credential = Credential . from ( {
192- challenge,
193- payload : { hash : receipt . transactionHash , type : 'hash' as const } ,
194- source : `did:pkh:eip155:${ chain . id } :${ accounts [ 1 ] . address } ` ,
195- } )
196-
197- const authResponse = await fetch ( httpServer . url , {
198- headers : { Authorization : Credential . serialize ( credential ) } ,
199- } )
200- expect ( authResponse . status ) . toBe ( 402 )
201-
202- const body = ( await authResponse . json ( ) ) as { detail : string }
203- expect ( body . detail ) . toContain ( 'Hash credentials cannot be used when `feePayer` is true.' )
204-
205- httpServer . close ( )
206- } )
207-
208- test ( 'behavior: verifies payment effects even when receipt.from differs' , async ( ) => {
209- const interceptingClient = createClient ( {
210- chain : client . chain ,
211- transport : custom ( {
212- async request ( args : any ) {
213- const result = await client . transport . request ( args )
214- if ( args ?. method === 'eth_getTransactionReceipt' ) {
215- return {
216- ...( result as any ) ,
217- from : accounts [ 0 ] . address ,
218- }
219- }
220- return result
221- } ,
222- } ) ,
223- } )
224-
225- const serverProxy = Mppx_server . create ( {
226- methods : [
227- tempo_server . charge ( {
228- getClient ( ) {
229- return interceptingClient
230- } ,
231- currency : asset ,
232- account : accounts [ 0 ] ,
233- } ) ,
234- ] ,
235- realm,
236- secretKey,
237- } )
238-
239- const httpServer = await Http . createServer ( async ( req , res ) => {
240- const result = await Mppx_server . toNodeListener ( serverProxy . charge ( { amount : '1' } ) ) (
241- req ,
242- res ,
243- )
244- if ( result . status === 402 ) return
245- res . end ( 'OK' )
246- } )
247-
248- const response = await fetch ( httpServer . url )
249- expect ( response . status ) . toBe ( 402 )
250-
251- const challenge = Challenge . fromResponse ( response , {
252- methods : [ tempo_client . charge ( ) ] ,
253- } )
254-
255- const { receipt } = await Actions . token . transferSync ( client , {
256- account : accounts [ 1 ] ,
257- amount : BigInt ( challenge . request . amount ) ,
258- to : challenge . request . recipient as Hex . Hex ,
259- token : challenge . request . currency as Hex . Hex ,
260- } )
261-
262- const credential = Credential . from ( {
263- challenge,
264- payload : { hash : receipt . transactionHash , type : 'hash' as const } ,
265- source : `did:pkh:eip155:${ chain . id } :${ accounts [ 1 ] . address } ` ,
266- } )
267-
268- const authResponse = await fetch ( httpServer . url , {
269- headers : { Authorization : Credential . serialize ( credential ) } ,
270- } )
271- expect ( authResponse . status ) . toBe ( 200 )
272-
273- httpServer . close ( )
274- } )
275-
276116 test ( 'behavior: rejects replayed transaction hash' , async ( ) => {
277117 const dedupServer = Mppx_server . create ( {
278118 methods : [
@@ -1417,43 +1257,6 @@ describe('tempo', () => {
14171257 httpServer . close ( )
14181258 } )
14191259
1420- test ( 'error: rejects push mode for fee-payer challenges' , async ( ) => {
1421- const mppx = Mppx_client . create ( {
1422- polyfill : false ,
1423- methods : [
1424- tempo_client ( {
1425- account : accounts [ 1 ] ,
1426- mode : 'push' ,
1427- getClient ( ) {
1428- return client
1429- } ,
1430- } ) ,
1431- ] ,
1432- } )
1433-
1434- const httpServer = await Http . createServer ( async ( req , res ) => {
1435- const result = await Mppx_server . toNodeListener (
1436- server . charge ( {
1437- feePayer : accounts [ 0 ] ,
1438- amount : '1' ,
1439- currency : asset ,
1440- recipient : accounts [ 0 ] . address ,
1441- } ) ,
1442- ) ( req , res )
1443- if ( result . status === 402 ) return
1444- res . end ( 'OK' )
1445- } )
1446-
1447- const response = await fetch ( httpServer . url )
1448- expect ( response . status ) . toBe ( 402 )
1449-
1450- await expect ( mppx . createCredential ( response ) ) . rejects . toThrow (
1451- '`feePayer: true` requires pull mode so the server can co-sign it.' ,
1452- )
1453-
1454- httpServer . close ( )
1455- } )
1456-
14571260 test ( 'behavior: fee payer with splits' , async ( ) => {
14581261 const mppx = Mppx_client . create ( {
14591262 polyfill : false ,
0 commit comments