-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
#include "hookapi.h" | ||
|
||
#define SVAR(x) &(x), sizeof(x) | ||
|
||
#define NOPE(x) \ | ||
{ \ | ||
return rollback((x), sizeof(x), __LINE__); \ | ||
} | ||
|
||
#define MULTIPLIER 0.2 // 0.2 (6 XAH for 30 LEDGERS == 0.2 XAH PER LEDGER) | ||
#define MAX 60 // 30 LEDGERS | ||
|
||
uint8_t bids_ns[32] = { | ||
0xAF, 0xD5, 0x20, 0x13, 0x12, 0xCC, 0xC1, 0xA5, | ||
0x41, 0x02, 0x63, 0x25, 0x9D, 0x0B, 0x22, 0x30, | ||
0x99, 0x18, 0x52, 0x16, 0x95, 0x5F, 0x8F, 0x6E, | ||
0x1C, 0x71, 0xF4, 0x14, 0xF0, 0x32, 0x48, 0xB6}; | ||
; | ||
|
||
int64_t hook(uint32_t r) | ||
{ | ||
_g(1, 1); | ||
// ACCOUNT: Origin Tx Account | ||
uint8_t otxn_accid[32]; | ||
otxn_field(otxn_accid + 12, 20, sfAccount); | ||
|
||
// ACCOUNT: Hook Account | ||
uint8_t hook_accid[32]; | ||
hook_account(hook_accid + 12, 20); | ||
|
||
// FILTER ON: ACCOUNT | ||
if (BUFFER_EQUAL_20(hook_accid + 12, otxn_accid + 12)) | ||
DONE("display.c: outgoing tx on `Account`."); | ||
|
||
int64_t tt = otxn_type(); | ||
if (tt != ttINVOKE && tt != ttPAYMENT) | ||
NOPE("display.c: Rejecting non-Invoke, non-Payment txn."); | ||
|
||
uint8_t amount_buffer[48]; | ||
otxn_slot(1); | ||
slot_subfield(1, sfAmount, 2); | ||
|
||
int64_t amount_xfl; | ||
uint32_t flags; | ||
if (tt == ttPAYMENT) | ||
{ | ||
// this will fail if flags isn't in the txn, that's also ok. | ||
otxn_field(&flags, 4, sfFlags); | ||
|
||
// check for partial payments (0x00020000) -> (0x00000200 LE) | ||
if (flags & 0x200U) | ||
NOPE("display.c: Partial payments are not supported."); | ||
|
||
otxn_field(SBUF(amount_buffer), sfAmount); | ||
|
||
amount_xfl = slot_float(2); | ||
|
||
if (amount_xfl < 0 || !float_compare(amount_xfl, 1, COMPARE_GREATER)) | ||
NOPE("display.c: Invalid sfAmount."); | ||
} | ||
|
||
// // Operation | ||
uint8_t op; | ||
if (otxn_param(&op, 1, "OP", 2) != 1) | ||
NOPE("display.c: Missing OP parameter on Invoke/Payment."); | ||
|
||
// sanity check | ||
if (op == 'B' && tt != ttPAYMENT) | ||
NOPE("display.c: Bid operations must be a payment transaction."); | ||
|
||
// sanity check | ||
if (op == 'U' && tt != ttINVOKE) | ||
NOPE("display.c: Update operations must be a invoke transaction."); | ||
|
||
int64_t count; | ||
if (state(&count, 8, hook_accid + 12, 20) == DOESNT_EXIST) | ||
{ | ||
// set current if initialization | ||
ASSERT(0 < state_set(&count, 8, hook_accid + 12, 20)); | ||
} | ||
|
||
switch (op) | ||
{ | ||
case 'B': | ||
{ | ||
uint8_t tid[40]; | ||
if (otxn_param(tid, 32, "ID", 2) != 32) | ||
NOPE("display.c: Missing ID parameter on Payment."); | ||
|
||
int64_t bid_count; | ||
state_foreign(&bid_count, 8, hook_accid + 12, 20, bids_ns, 32, hook_accid + 12, 20); | ||
|
||
int64_t end_ledger; | ||
int64_t cur_ledger = ledger_seq(); | ||
if (state_foreign(&end_ledger, 8, hook_accid + 12, 20, 0, 32, hook_accid + 12, 20) == DOESNT_EXIST || end_ledger < cur_ledger) | ||
{ | ||
end_ledger = cur_ledger; | ||
} | ||
|
||
// calculate ledgers | ||
int64_t amount_int = float_int(amount_xfl, 0, 1); | ||
int64_t duration = amount_int / MULTIPLIER; | ||
if (duration > MAX) | ||
NOPE("display.c: Duration cannot be more than 60 ledgers."); | ||
|
||
end_ledger += duration; | ||
UINT64_TO_BUF(tid + 32, end_ledger); | ||
ASSERT(0 < state_foreign_set(tid, 40, &bid_count, 8, bids_ns, 32, hook_accid + 12, 20)); | ||
|
||
bid_count++; | ||
ASSERT(0 < state_foreign_set(&bid_count, 8, hook_accid + 12, 20, bids_ns, 32, hook_accid + 12, 20)); | ||
ASSERT(0 < state_foreign_set(&end_ledger, 8, hook_accid + 12, 20, 0, 32, hook_accid + 12, 20)); | ||
TRACESTR("display.c: Bid."); | ||
return accept(SBUF("display.c: Bid."), __LINE__); | ||
} | ||
case 'U': | ||
{ | ||
uint8_t tid[40]; | ||
state_foreign(tid, 40, &count, 8, bids_ns, 32, hook_accid + 12, 20); | ||
uint64_t final_ledger = UINT64_FROM_BUF(tid + 32); | ||
int64_t cur_sequence = ledger_seq(); | ||
if (cur_sequence < final_ledger) | ||
{ | ||
NOPE("display.c: Duration has not expired."); | ||
} | ||
|
||
state_foreign_set(0, 0, &count, 8, bids_ns, 32, hook_accid + 12, 20); | ||
|
||
count++; | ||
ASSERT(0 < state_set(&count, 8, hook_accid + 12, 20)); | ||
TRACESTR("display.c: Update."); | ||
return accept(SBUF("display.c: Update."), __LINE__); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
// xrpl | ||
import { | ||
URITokenMint, | ||
Payment, | ||
Invoke, | ||
SetHookFlags, | ||
convertStringToHex, | ||
TransactionMetadata, | ||
xrpToDrops, | ||
} from '@transia/xrpl' | ||
// xrpl-helpers | ||
import { | ||
XrplIntegrationTestContext, | ||
setupClient, | ||
teardownClient, | ||
serverUrl, | ||
close, | ||
} from '@transia/hooks-toolkit/dist/npm/src/libs/xrpl-helpers' | ||
// src | ||
import { | ||
SetHookParams, | ||
createHookPayload, | ||
setHooksV3, | ||
iHookParamEntry, | ||
iHookParamName, | ||
iHookParamValue, | ||
ExecutionUtility, | ||
Xrpld, | ||
StateUtility, | ||
hexNamespace, | ||
padHexString, | ||
flipHex, | ||
} from '@transia/hooks-toolkit/dist/npm/src' | ||
import { hashURIToken } from '@transia/xrpl/dist/npm/utils/hashes' | ||
import { | ||
decodeModel, | ||
hexToUInt64, | ||
xrpAddressToHex, | ||
} from '@transia/hooks-toolkit/dist/npm/src/libs/binary-models' | ||
import { DisplayModel } from './models/DisplayModel' | ||
|
||
// LevelThree: ACCEPT: success | ||
|
||
describe('hunt', () => { | ||
let testContext: XrplIntegrationTestContext | ||
|
||
beforeAll(async () => { | ||
testContext = await setupClient(serverUrl) | ||
const hookWallet = testContext.hook1 | ||
|
||
const hook1 = createHookPayload({ | ||
version: 0, | ||
createFile: 'display', | ||
namespace: 'display', | ||
flags: SetHookFlags.hsfOverride, | ||
hookOnArray: ['Payment', 'Invoke'], | ||
}) | ||
await setHooksV3({ | ||
client: testContext.client, | ||
seed: hookWallet.seed, | ||
hooks: [{ Hook: hook1 }], | ||
} as SetHookParams) | ||
}) | ||
afterAll(async () => teardownClient(testContext)) | ||
|
||
it('display - success', async () => { | ||
const aliceWallet = testContext.alice | ||
const hookWallet = testContext.hook1 | ||
|
||
// Bob: Mint and Sell | ||
const random = Math.random() | ||
const builtTx1: URITokenMint = { | ||
TransactionType: 'URITokenMint', | ||
Account: aliceWallet.classicAddress, | ||
URI: convertStringToHex(`ipfs://${random}`), | ||
} | ||
await Xrpld.submit(testContext.client, { | ||
wallet: aliceWallet, | ||
tx: builtTx1, | ||
}) | ||
await close(testContext.client) | ||
const uriTokenID = hashURIToken( | ||
aliceWallet.classicAddress, | ||
`ipfs://${random}` | ||
) | ||
|
||
console.log(uriTokenID) | ||
|
||
const param1 = new iHookParamEntry( | ||
new iHookParamName('OP'), | ||
new iHookParamValue('B') | ||
) | ||
const param2 = new iHookParamEntry( | ||
new iHookParamName('ID'), | ||
new iHookParamValue( | ||
'35D1168C6D5B107A3B884B055D0657E36196882AAA16C68E345AC998717E86B3', | ||
true | ||
) | ||
) | ||
const builtTx: Payment = { | ||
TransactionType: 'Payment', | ||
Account: aliceWallet.classicAddress, | ||
Destination: hookWallet.classicAddress, | ||
Amount: xrpToDrops('6'), | ||
HookParameters: [param1.toXrpl(), param2.toXrpl()], | ||
} | ||
const result = await Xrpld.submit(testContext.client, { | ||
wallet: aliceWallet, | ||
tx: builtTx, | ||
}) | ||
const hookExecutions = await ExecutionUtility.getHookExecutionsFromMeta( | ||
testContext.client, | ||
result.meta as TransactionMetadata | ||
) | ||
console.log(hookExecutions.executions[0].HookReturnString) | ||
|
||
await close(testContext.client) | ||
|
||
const currentState = await StateUtility.getHookState( | ||
testContext.client, | ||
testContext.hook1.classicAddress, | ||
padHexString(xrpAddressToHex(testContext.hook1.classicAddress)), | ||
hexNamespace('display') | ||
) | ||
|
||
console.log(hexToUInt64(flipHex(currentState.HookStateData))) | ||
|
||
console.log(padHexString(currentState.HookStateData, 64)) | ||
console.log(hexNamespace('bids')) | ||
|
||
const state = await StateUtility.getHookState( | ||
testContext.client, | ||
testContext.hook1.classicAddress, | ||
padHexString(currentState.HookStateData, 64), | ||
hexNamespace('bids') | ||
) | ||
|
||
console.log(decodeModel(state.HookStateData, DisplayModel)) | ||
|
||
for (let index = 0; index < 30; index++) { | ||
await close(testContext.client) | ||
} | ||
|
||
const tx2Param1 = new iHookParamEntry( | ||
new iHookParamName('OP'), | ||
new iHookParamValue('U') | ||
) | ||
const builtTx2: Invoke = { | ||
TransactionType: 'Invoke', | ||
Account: aliceWallet.classicAddress, | ||
Destination: hookWallet.classicAddress, | ||
HookParameters: [tx2Param1.toXrpl()], | ||
} | ||
const result2 = await Xrpld.submit(testContext.client, { | ||
wallet: aliceWallet, | ||
tx: builtTx2, | ||
}) | ||
const hookExecutions2 = await ExecutionUtility.getHookExecutionsFromMeta( | ||
testContext.client, | ||
result2.meta as TransactionMetadata | ||
) | ||
console.log(hookExecutions2.executions[0].HookReturnString) | ||
|
||
await close(testContext.client) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { | ||
BaseModel, | ||
Hash256, | ||
Metadata, | ||
UInt64, | ||
} from '@transia/hooks-toolkit/dist/npm/src/libs/binary-models' | ||
|
||
export class DisplayModel extends BaseModel { | ||
id: Hash256 | ||
lastLedger: UInt64 | ||
|
||
constructor(id: Hash256, lastLedger: UInt64) { | ||
super() | ||
this.id = id | ||
this.lastLedger = lastLedger | ||
} | ||
|
||
getMetadata(): Metadata { | ||
return [ | ||
{ field: 'id', type: 'hash256' }, | ||
{ field: 'lastLedger', type: 'uint64' }, | ||
] | ||
} | ||
|
||
toJSON() { | ||
return { | ||
id: this.id, | ||
lastLedger: this.lastLedger, | ||
} | ||
} | ||
} |