mirror of
https://github.com/Xahau/xahau.js.git
synced 2026-08-18 22:22:53 +00:00
HookOnV2 Amendment (#51)
This commit is contained in:
@@ -5,6 +5,7 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
|
||||
## Unreleased Changes
|
||||
|
||||
### Added
|
||||
* Support for HookOnV2 Amendment
|
||||
* Support for IOUClaimReward Amendment
|
||||
* Support for NamedHooks
|
||||
* Support for the `simulate` RPC ([XLS-69](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0069-simulate))
|
||||
|
||||
@@ -86,6 +86,14 @@ export interface Hook {
|
||||
* The transactions that triggers the hook. Represented as a 256Hash
|
||||
*/
|
||||
HookOn?: string
|
||||
/**
|
||||
* The incoming transactions that triggers to the hook. Represented as a 256Hash
|
||||
*/
|
||||
HookOnIncoming?: string
|
||||
/**
|
||||
* The outgoing transactions that triggers from the hook. Represented as a 256Hash
|
||||
*/
|
||||
HookOnOutgoing?: string
|
||||
/**
|
||||
* The transactions that can emit from the hook. Represented as a 256Hash
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,16 @@ export default interface HookDefintion
|
||||
*/
|
||||
HookOn?: string
|
||||
|
||||
/**
|
||||
* The incoming transactions that triggers to the hook. Represented as a 256Hash
|
||||
*/
|
||||
HookOnIncoming?: string
|
||||
|
||||
/**
|
||||
* The outgoing transactions that triggers from the hook. Represented as a 256Hash
|
||||
*/
|
||||
HookOnOutgoing?: string
|
||||
|
||||
/**
|
||||
* The namespace of the hook.
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,7 @@ const HOOKNAME_REGEX = /^[0-9A-Fa-f]{8,32}$/u
|
||||
* @param tx - An SetHook Transaction.
|
||||
* @throws When the SetHook is Malformed.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- okay for this method
|
||||
export function validateSetHook(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
@@ -45,12 +46,29 @@ export function validateSetHook(tx: Record<string, unknown>): void {
|
||||
for (const hook of tx.Hooks) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be a Hook
|
||||
const hookObject = hook as Hook
|
||||
const { HookOn, HookCanEmit, HookNamespace, HookName } = hookObject.Hook
|
||||
const {
|
||||
HookOn,
|
||||
HookOnIncoming,
|
||||
HookOnOutgoing,
|
||||
HookCanEmit,
|
||||
HookNamespace,
|
||||
HookName,
|
||||
} = hookObject.Hook
|
||||
if (HookOn !== undefined && !HEX_REGEX.test(HookOn)) {
|
||||
throw new ValidationError(
|
||||
`SetHook: HookOn in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||
)
|
||||
}
|
||||
if (HookOnIncoming !== undefined && !HEX_REGEX.test(HookOnIncoming)) {
|
||||
throw new ValidationError(
|
||||
`SetHook: HookOnIncoming in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||
)
|
||||
}
|
||||
if (HookOnOutgoing !== undefined && !HEX_REGEX.test(HookOnOutgoing)) {
|
||||
throw new ValidationError(
|
||||
`SetHook: HookOnOutgoing in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||
)
|
||||
}
|
||||
if (HookCanEmit !== undefined && !HEX_REGEX.test(HookCanEmit)) {
|
||||
throw new ValidationError(
|
||||
`SetHook: HookCanEmit in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||
|
||||
@@ -93,4 +93,46 @@ describe('SetHook', function () {
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'hook on incoming/outgoing',
|
||||
async () => {
|
||||
const setHookTx: SetHook = {
|
||||
TransactionType: 'SetHook',
|
||||
Account: wallet.classicAddress,
|
||||
Hooks: [
|
||||
{
|
||||
Hook: {
|
||||
CreateCode: acceptHook,
|
||||
HookApiVersion: 0,
|
||||
HookOnIncoming: '00'.repeat(32),
|
||||
// eslint-disable-next-line no-inline-comments -- for readability
|
||||
HookOnOutgoing: `01${'00'.repeat(31)}`, // should be different from HookOnIncoming
|
||||
HookNamespace: '00'.repeat(32),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
await testTransaction(testContext.client, setHookTx, wallet)
|
||||
|
||||
const ledgerEntryResponse = await testContext.client.request({
|
||||
command: 'ledger_entry',
|
||||
hook: { account: wallet.classicAddress },
|
||||
})
|
||||
const node = ledgerEntryResponse.result.node as Hook
|
||||
const hook = node.Hooks[0].Hook
|
||||
const hookHash = hook.HookHash!
|
||||
|
||||
const hookDefinitionResponse = await testContext.client.request({
|
||||
command: 'ledger_entry',
|
||||
hook_definition: hookHash,
|
||||
})
|
||||
const hookDefinitionNode = hookDefinitionResponse.result
|
||||
.node as HookDefinition
|
||||
expect(hookDefinitionNode.HookOn).toBeUndefined()
|
||||
expect(hookDefinitionNode.HookOnIncoming).toBeDefined()
|
||||
expect(hookDefinitionNode.HookOnOutgoing).toBeDefined()
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -67,6 +67,10 @@ describe('SetHook', function () {
|
||||
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
||||
HookOn:
|
||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||
HookOnIncoming:
|
||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||
HookOnOutgoing:
|
||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||
Flags: 1,
|
||||
HookApiVersion: 0,
|
||||
HookNamespace:
|
||||
@@ -94,30 +98,31 @@ describe('SetHook', function () {
|
||||
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
||||
})
|
||||
|
||||
it(`throws w/ invalid HookOn in Hooks`, function () {
|
||||
setHookTx.SignerQuorum = 2
|
||||
setHookTx.Hooks = [
|
||||
{
|
||||
Hook: {
|
||||
CreateCode:
|
||||
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
||||
HookOn: '',
|
||||
Flags: 1,
|
||||
HookApiVersion: 0,
|
||||
HookNamespace:
|
||||
'4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9',
|
||||
it.each(['HookOn', 'HookOnIncoming', 'HookOnOutgoing'])(
|
||||
`throws w/ invalid %s in Hooks`,
|
||||
function (field: string) {
|
||||
setHookTx.Hooks = [
|
||||
{
|
||||
Hook: {
|
||||
CreateCode:
|
||||
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
||||
[field]: '',
|
||||
Flags: 1,
|
||||
HookApiVersion: 0,
|
||||
HookNamespace:
|
||||
'4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9',
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
const errorMessage =
|
||||
'SetHook: HookOn in Hook must be a 256-bit (32-byte) hexadecimal value'
|
||||
assert.throws(
|
||||
() => validateSetHook(setHookTx),
|
||||
ValidationError,
|
||||
errorMessage,
|
||||
)
|
||||
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
||||
})
|
||||
]
|
||||
const errorMessage = `SetHook: ${field} in Hook must be a 256-bit (32-byte) hexadecimal value`
|
||||
assert.throws(
|
||||
() => validateSetHook(setHookTx),
|
||||
ValidationError,
|
||||
errorMessage,
|
||||
)
|
||||
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
||||
},
|
||||
)
|
||||
|
||||
it(`throws w/ invalid HookCanEmit in Hooks`, function () {
|
||||
setHookTx.Hooks = [
|
||||
|
||||
Reference in New Issue
Block a user