Skip to content

Instantly share code, notes, and snippets.

@dangell7
Last active June 14, 2022 23:51
Show Gist options
  • Save dangell7/44334bd8930b8503d156d39021f3c6fb to your computer and use it in GitHub Desktop.
Save dangell7/44334bd8930b8503d156d39021f3c6fb to your computer and use it in GitHub Desktop.
#define HAS_CALLBACK
#include <stdint.h>
#include "hookapi.h"
#define ttNFTOKEN_MINT 25
#define tfBURNABLE 0x00000001UL
#define tfONLYXRP 0x00000002UL
#define tfTRUSTLINE 0x00000004UL
#define tfTRANSFERABLE 0x00000008UL
// NFT TOKEN TAXON
#define ENCODE_TAXON_NFT_SIZE 6
#define ENCODE_TAXON_NFT(buf_out, taxon )\
ENCODE_UINT32_UNCOMMON(buf_out, taxon, 0x2A );
#define _02_42_ENCODE_TAXON_NFT(buf_out, taxon )\
ENCODE_TAXON_NFT(buf_out, taxon );
// URI
// #define ENCODE_VL_COMMON_SIZE ?
#define ENCODE_VL_COMMON(buf_out, hex, size) \
{ \
buf_out[0] = 0x75U; \
buf_out[1] = 0x03U; \
int i = 0; \
size += 2; \
for(i = size - 1; i >= 2; --i) { \
buf_out[i] = (hex >> (i - 2) * 8) & 0xFFU;\
} \
}
#define _07_XX_ENCODE_VL_COMMON(buf_out, hex, size) \
int size = sizeof(hex) / 2; \
ENCODE_VL_COMMON(buf_out, hex, size) \
// #ifdef HAS_CALLBACK
// #define PREPARE_NFT_MINT_SIMPLE_SIZE 254U
// #else
// #define PREPARE_NFT_MINT_SIMPLE_SIZE 232U
// #endif
#define PREPARE_NFT_MINT_SIMPLE_SIZE 240
#define PREPARE_NFT_MINT_SIMPLE(buf_out_master, flags, taxon, uri) \
{ \
uint8_t *buf_out = buf_out_master; \
uint8_t acc[20]; \
uint32_t cls = (uint32_t)ledger_seq(); \
hook_account(SBUF(acc)); \
_01_02_ENCODE_TT(buf_out, ttNFTOKEN_MINT); /* uint16 | size 3 */\
_02_02_ENCODE_FLAGS(buf_out, flags); /* uint32 | size 5 */\
_02_04_ENCODE_SEQUENCE(buf_out, 0); /* uint32 | size 5 */\
_02_26_ENCODE_FLS(buf_out, cls + 1); /* uint32 | size 6 */\
_02_27_ENCODE_LLS(buf_out, cls + 5); /* uint32 | size 6 */\
_02_42_ENCODE_TAXON_NFT(buf_out, taxon); /* amount | size 6 */\
_07_XX_ENCODE_VL_COMMON(buf_out, uri); /* vl. | size 5 */\
_06_08_ENCODE_DROPS_FEE(buf_out, 120); /* amount | size 9 */\
uint8_t* fee_ptr = buf_out;\
_07_03_ENCODE_SIGNING_PUBKEY_NULL(buf_out); /* pk | size 35 */\
_08_01_ENCODE_ACCOUNT_SRC(buf_out, acc); /* account | size 22 */\
int64_t edlen = etxn_details((uint32_t)buf_out, PREPARE_NFT_MINT_SIMPLE_SIZE); /* emitdet | size 1?? */\
}
int64_t cbak(uint32_t reserved)
{
TRACESTR("Carbon: callback called.");
return 0;
}
int64_t hook(uint32_t reserved)
{
TRACESTR("Carbon: started");
// before we start calling hook-api functions we should tell the hook how many tx we intend to create
etxn_reserve(1); // we are going to emit 1 transaction
// hooks communicate accounts via the 20 byte account ID, this can be generated from an raddr like so
// a more efficient way to do this is precompute the account-id from the raddr (if the raddr never changes)
uint8_t carbon_accid[20];
int64_t ret = util_accid(
SBUF(carbon_accid), /* <-- generate into this buffer */
SBUF("rfCarbonVNTuXckX6x2qTMFmFSnm6dEWGX") ); /* <-- from this r-addr */
TRACEVAR(ret);
// this api fetches the AccountID of the account the hook currently executing is installed on
// since hooks can be triggered by both incoming and ougoing transactions this is important to know
unsigned char hook_accid[20];
hook_account((uint32_t)hook_accid, 20);
// NB:
// almost all of the hook apis require a buffer pointer and buffer length to be supplied ... to make this a
// little easier to code a macro: `SBUF(your_buffer)` expands to `your_buffer, sizeof(your_buffer)`
// next fetch the sfAccount field from the originating transaction
uint8_t account_field[20];
int32_t account_field_len = otxn_field(SBUF(account_field), sfAccount);
TRACEVAR(account_field_len);
if (account_field_len < 20) // negative values indicate errors from every api
rollback(SBUF("Carbon: sfAccount field missing!!!"), 1); // this code could never be hit in prod
// but it's here for completeness
// compare the "From Account" (sfAccount) on the transaction with the account the hook is running on
int equal = 0; BUFFER_EQUAL(equal, hook_accid, account_field, 20);
if (!equal)
{
// if the accounts are not equal (memcmp != 0) the otxn was sent to the hook account by someone else
// accept() it and end the hook execution here
accept(SBUF("Carbon: Incoming transaction"), 2);
}
// execution to here means the user has sent a valid transaction FROM the account the hook is installed on
// fetch the sent Amount
// Amounts can be 384 bits or 64 bits. If the Amount is an XRP value it will be 64 bits.
unsigned char amount_buffer[48];
int64_t amount_len = otxn_field(SBUF(amount_buffer), sfAmount);
int64_t drops_to_send = 1000; // this will be the default
if (amount_len != 8)
{
// you can trace the behaviour of your hook using the trace(buf, size, as_hex) api
// which will output to xrpld's trace log
TRACESTR("Carbon: Non-xrp transaction detected, sending default 1000 drops to rfCarbon");
} else
{
TRACESTR("Carbon: XRP transaction detected, computing 1% to send to rfCarbon");
int64_t otxn_drops = AMOUNT_TO_DROPS(amount_buffer);
TRACEVAR(otxn_drops);
if (otxn_drops > 100000) // if its less we send the default amount. or if there was an error we send default
drops_to_send = (int64_t)((double)otxn_drops * 0.01f); // otherwise we send 1%
}
TRACEVAR(drops_to_send);
// Mint Flags
int flags = tfBURNABLE + tfTRANSFERABLE;
// create a buffer to write the emitted transaction into
unsigned char tx[PREPARE_NFT_MINT_SIMPLE_SIZE];
// we will use an XRP payment macro, this will populate the buffer with a serialized binary transaction
// Parameter list: ( buf_out, drops_amount, to_address, dest_tag, src_tag )
PREPARE_NFT_MINT_SIMPLE(tx, flags, 0, 0x112211);
// trace(SBUF("EMITTED"), tx, PREPARE_NFT_MINT_SIMPLE_SIZE, 1);
TRACEHEX(tx)
// emit the transaction
uint8_t emithash[32];
int64_t emit_result = emit(SBUF(emithash), SBUF(tx));
TRACEVAR(emit_result);
// accept and allow the original transaction through
accept(SBUF("Carbon: Emitted transaction"), 0);
return 0;
}
/**
* This file contains programmatically generated sf field codes
*/
#define sfCloseResolution ((16U << 16U) + 1U)
#define sfMethod ((16U << 16U) + 2U)
#define sfTransactionResult ((16U << 16U) + 3U)
#define sfTickSize ((16U << 16U) + 16U)
#define sfUNLModifyDisabling ((16U << 16U) + 17U)
#define sfHookResult ((16U << 16U) + 18U)
#define sfLedgerEntryType ((1U << 16U) + 1U)
#define sfTransactionType ((1U << 16U) + 2U)
#define sfSignerWeight ((1U << 16U) + 3U)
#define sfTransferFee ((1U << 16U) + 4U)
#define sfVersion ((1U << 16U) + 16U)
#define sfHookStateChangeCount ((1U << 16U) + 17U)
#define sfHookEmitCount ((1U << 16U) + 18U)
#define sfHookExecutionIndex ((1U << 16U) + 19U)
#define sfHookApiVersion ((1U << 16U) + 20U)
#define sfFlags ((2U << 16U) + 2U)
#define sfSourceTag ((2U << 16U) + 3U)
#define sfSequence ((2U << 16U) + 4U)
#define sfPreviousTxnLgrSeq ((2U << 16U) + 5U)
#define sfLedgerSequence ((2U << 16U) + 6U)
#define sfCloseTime ((2U << 16U) + 7U)
#define sfParentCloseTime ((2U << 16U) + 8U)
#define sfSigningTime ((2U << 16U) + 9U)
#define sfExpiration ((2U << 16U) + 10U)
#define sfTransferRate ((2U << 16U) + 11U)
#define sfWalletSize ((2U << 16U) + 12U)
#define sfOwnerCount ((2U << 16U) + 13U)
#define sfDestinationTag ((2U << 16U) + 14U)
#define sfHighQualityIn ((2U << 16U) + 16U)
#define sfHighQualityOut ((2U << 16U) + 17U)
#define sfLowQualityIn ((2U << 16U) + 18U)
#define sfLowQualityOut ((2U << 16U) + 19U)
#define sfQualityIn ((2U << 16U) + 20U)
#define sfQualityOut ((2U << 16U) + 21U)
#define sfStampEscrow ((2U << 16U) + 22U)
#define sfBondAmount ((2U << 16U) + 23U)
#define sfLoadFee ((2U << 16U) + 24U)
#define sfOfferSequence ((2U << 16U) + 25U)
#define sfFirstLedgerSequence ((2U << 16U) + 26U)
#define sfLastLedgerSequence ((2U << 16U) + 27U)
#define sfTransactionIndex ((2U << 16U) + 28U)
#define sfOperationLimit ((2U << 16U) + 29U)
#define sfReferenceFeeUnits ((2U << 16U) + 30U)
#define sfReserveBase ((2U << 16U) + 31U)
#define sfReserveIncrement ((2U << 16U) + 32U)
#define sfSetFlag ((2U << 16U) + 33U)
#define sfClearFlag ((2U << 16U) + 34U)
#define sfSignerQuorum ((2U << 16U) + 35U)
#define sfCancelAfter ((2U << 16U) + 36U)
#define sfFinishAfter ((2U << 16U) + 37U)
#define sfSignerListID ((2U << 16U) + 38U)
#define sfSettleDelay ((2U << 16U) + 39U)
#define sfTicketCount ((2U << 16U) + 40U)
#define sfTicketSequence ((2U << 16U) + 41U)
#define sfTokenTaxon ((2U << 16U) + 42U)
#define sfMintedTokens ((2U << 16U) + 43U)
#define sfBurnedTokens ((2U << 16U) + 44U)
#define sfHookStateCount ((2U << 16U) + 45U)
#define sfEmitGeneration ((2U << 16U) + 46U)
#define sfIndexNext ((3U << 16U) + 1U)
#define sfIndexPrevious ((3U << 16U) + 2U)
#define sfBookNode ((3U << 16U) + 3U)
#define sfOwnerNode ((3U << 16U) + 4U)
#define sfBaseFee ((3U << 16U) + 5U)
#define sfExchangeRate ((3U << 16U) + 6U)
#define sfLowNode ((3U << 16U) + 7U)
#define sfHighNode ((3U << 16U) + 8U)
#define sfDestinationNode ((3U << 16U) + 9U)
#define sfCookie ((3U << 16U) + 10U)
#define sfServerVersion ((3U << 16U) + 11U)
#define sfOfferNode ((3U << 16U) + 12U)
#define sfEmitBurden ((3U << 16U) + 13U)
#define sfHookOn ((3U << 16U) + 16U)
#define sfHookInstructionCount ((3U << 16U) + 17U)
#define sfHookReturnCode ((3U << 16U) + 18U)
#define sfReferenceCount ((3U << 16U) + 19U)
#define sfEmailHash ((4U << 16U) + 1U)
#define sfTakerPaysCurrency ((17U << 16U) + 1U)
#define sfTakerPaysIssuer ((17U << 16U) + 2U)
#define sfTakerGetsCurrency ((17U << 16U) + 3U)
#define sfTakerGetsIssuer ((17U << 16U) + 4U)
#define sfLedgerHash ((5U << 16U) + 1U)
#define sfParentHash ((5U << 16U) + 2U)
#define sfTransactionHash ((5U << 16U) + 3U)
#define sfAccountHash ((5U << 16U) + 4U)
#define sfPreviousTxnID ((5U << 16U) + 5U)
#define sfLedgerIndex ((5U << 16U) + 6U)
#define sfWalletLocator ((5U << 16U) + 7U)
#define sfRootIndex ((5U << 16U) + 8U)
#define sfAccountTxnID ((5U << 16U) + 9U)
#define sfTokenID ((5U << 16U) + 10U)
#define sfEmitParentTxnID ((5U << 16U) + 11U)
#define sfEmitNonce ((5U << 16U) + 12U)
#define sfEmitHookHash ((5U << 16U) + 13U)
#define sfBookDirectory ((5U << 16U) + 16U)
#define sfInvoiceID ((5U << 16U) + 17U)
#define sfNickname ((5U << 16U) + 18U)
#define sfAmendment ((5U << 16U) + 19U)
#define sfDigest ((5U << 16U) + 21U)
#define sfChannel ((5U << 16U) + 22U)
#define sfConsensusHash ((5U << 16U) + 23U)
#define sfCheckID ((5U << 16U) + 24U)
#define sfValidatedHash ((5U << 16U) + 25U)
#define sfPreviousPageMin ((5U << 16U) + 26U)
#define sfNextPageMin ((5U << 16U) + 27U)
#define sfBuyOffer ((5U << 16U) + 28U)
#define sfSellOffer ((5U << 16U) + 29U)
#define sfHookStateKey ((5U << 16U) + 30U)
#define sfHookHash ((5U << 16U) + 31U)
#define sfHookNamespace ((5U << 16U) + 32U)
#define sfHookSetTxnID ((5U << 16U) + 33U)
#define sfAmount ((6U << 16U) + 1U)
#define sfBalance ((6U << 16U) + 2U)
#define sfLimitAmount ((6U << 16U) + 3U)
#define sfTakerPays ((6U << 16U) + 4U)
#define sfTakerGets ((6U << 16U) + 5U)
#define sfLowLimit ((6U << 16U) + 6U)
#define sfHighLimit ((6U << 16U) + 7U)
#define sfFee ((6U << 16U) + 8U)
#define sfSendMax ((6U << 16U) + 9U)
#define sfDeliverMin ((6U << 16U) + 10U)
#define sfMinimumOffer ((6U << 16U) + 16U)
#define sfRippleEscrow ((6U << 16U) + 17U)
#define sfDeliveredAmount ((6U << 16U) + 18U)
#define sfBrokerFee ((6U << 16U) + 19U)
#define sfPublicKey ((7U << 16U) + 1U)
#define sfMessageKey ((7U << 16U) + 2U)
#define sfSigningPubKey ((7U << 16U) + 3U)
#define sfTxnSignature ((7U << 16U) + 4U)
#define sfURI ((7U << 16U) + 5U)
#define sfSignature ((7U << 16U) + 6U)
#define sfDomain ((7U << 16U) + 7U)
#define sfFundCode ((7U << 16U) + 8U)
#define sfRemoveCode ((7U << 16U) + 9U)
#define sfExpireCode ((7U << 16U) + 10U)
#define sfCreateCode ((7U << 16U) + 11U)
#define sfMemoType ((7U << 16U) + 12U)
#define sfMemoData ((7U << 16U) + 13U)
#define sfMemoFormat ((7U << 16U) + 14U)
#define sfFulfillment ((7U << 16U) + 16U)
#define sfCondition ((7U << 16U) + 17U)
#define sfMasterSignature ((7U << 16U) + 18U)
#define sfUNLModifyValidator ((7U << 16U) + 19U)
#define sfValidatorToDisable ((7U << 16U) + 20U)
#define sfValidatorToReEnable ((7U << 16U) + 21U)
#define sfHookStateData ((7U << 16U) + 22U)
#define sfHookReturnString ((7U << 16U) + 23U)
#define sfHookParameterName ((7U << 16U) + 24U)
#define sfHookParameterValue ((7U << 16U) + 25U)
#define sfAccount ((8U << 16U) + 1U)
#define sfOwner ((8U << 16U) + 2U)
#define sfDestination ((8U << 16U) + 3U)
#define sfIssuer ((8U << 16U) + 4U)
#define sfAuthorize ((8U << 16U) + 5U)
#define sfUnauthorize ((8U << 16U) + 6U)
#define sfRegularKey ((8U << 16U) + 8U)
#define sfMinter ((8U << 16U) + 9U)
#define sfEmitCallback ((8U << 16U) + 10U)
#define sfHookAccount ((8U << 16U) + 16U)
#define sfIndexes ((19U << 16U) + 1U)
#define sfHashes ((19U << 16U) + 2U)
#define sfAmendments ((19U << 16U) + 3U)
#define sfTokenOffers ((19U << 16U) + 4U)
#define sfPaths ((18U << 16U) + 1U)
#define sfTransactionMetaData ((14U << 16U) + 2U)
#define sfCreatedNode ((14U << 16U) + 3U)
#define sfDeletedNode ((14U << 16U) + 4U)
#define sfModifiedNode ((14U << 16U) + 5U)
#define sfPreviousFields ((14U << 16U) + 6U)
#define sfFinalFields ((14U << 16U) + 7U)
#define sfNewFields ((14U << 16U) + 8U)
#define sfTemplateEntry ((14U << 16U) + 9U)
#define sfMemo ((14U << 16U) + 10U)
#define sfSignerEntry ((14U << 16U) + 11U)
#define sfNonFungibleToken ((14U << 16U) + 12U)
#define sfEmitDetails ((14U << 16U) + 13U)
#define sfHook ((14U << 16U) + 14U)
#define sfSigner ((14U << 16U) + 16U)
#define sfMajority ((14U << 16U) + 18U)
#define sfDisabledValidator ((14U << 16U) + 19U)
#define sfEmittedTxn ((14U << 16U) + 20U)
#define sfHookExecution ((14U << 16U) + 21U)
#define sfHookDefinition ((14U << 16U) + 22U)
#define sfHookParameter ((14U << 16U) + 23U)
#define sfHookGrant ((14U << 16U) + 24U)
#define sfSigners ((15U << 16U) + 3U)
#define sfSignerEntries ((15U << 16U) + 4U)
#define sfTemplate ((15U << 16U) + 5U)
#define sfNecessary ((15U << 16U) + 6U)
#define sfSufficient ((15U << 16U) + 7U)
#define sfAffectedNodes ((15U << 16U) + 8U)
#define sfMemos ((15U << 16U) + 9U)
#define sfNonFungibleTokens ((15U << 16U) + 10U)
#define sfHooks ((15U << 16U) + 11U)
#define sfMajorities ((15U << 16U) + 16U)
#define sfDisabledValidators ((15U << 16U) + 17U)
#define sfHookExecutions ((15U << 16U) + 18U)
#define sfHookParameters ((15U << 16U) + 19U)
#define sfHookGrants ((15U << 16U) + 20U)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment