#!/usr/bin/fift -s "TonUtil.fif" include "GetOpt.fif" include { show-options-help 1 halt } : usage "dns-msg-body.boc" =: savefile begin-options " [-o] (add|update|prolong) ... " +cr +tab +"Creates the internal message body containing a request to automatic DNS smart contract created by new-auto-dns.fif, " +"to be sent later with a suitable payment from a wallet to , and saves it into ('" savefile $+ +"' by default). " +"The operation to be performed is one of" +cr +tab +"add { owner | cat (smc | next | adnl | text ) }" +cr +tab +"update { owner | cat (smc | next | adnl | text ) }" +cr +tab +"prolong " disable-digit-options generic-help-setopt "o" "--output" { =: savefile } short-long-option-arg "Sets output file for generated initialization message ('" savefile $+ +"' by default)" option-help "h" "--help" { usage } short-long-option "Shows a help message" option-help parse-options $# 4 < ' usage if 4 :$1..n $1 true parse-load-address =: bounce 2=: dest-addr $2 dup =: main-op-name atom =: main-op $3 dup =: subdomain $len 127 > abort"subdomain name too long" $4 parse-int dup 30 1<< < { now + } if =: expire-at { $* @ dup null? { second $@ ! } { drop } cond } : @skip { $* @ null? } : @end? { $* @ uncons $* ! } : @next { @next drop } 4 times main-op dup `add eq? over `update eq? or swap `prolong eq? or { "unknown main operation '" main-op-name $+ +"'; one of 'add', 'update' or 'prolong' expected" abort } ifnot main-op `prolong eq? not =: need-params $# 4 > need-params <> abort"extra parameters, or no parameters for chosen main operation" variable Values dictnew Values ! // ( i c -- ) { over 0= abort"category cannot be zero" idict!+ not abort"duplicate category id" Values ! } : register-value { @end? abort"category number expected" @next (number) 1 <> abort"category must be integer" dup 16 fits not abort"category does not fit into 16 bit integer" dup 0= abort"category must be non-zero" } : parse-cat-num { @end? abort"smart contract address expected" @next false parse-load-address drop } : cl-parse-smc-addr { @end? abort"adnl address expected" @next parse-adnl-addr } : cl-parse-adnl-addr { } : serialize-smc-addr { } : serialize-next-resolver { } : serialize-adnl-addr { } : serialize-text { @end? abort"subdomain record value expected" @next dup "smc" $= { drop cl-parse-smc-addr serialize-smc-addr } { dup "next" $= { drop cl-parse-smc-addr serialize-next-resolver } { dup "adnl" $= { drop cl-parse-adnl-addr serialize-adnl-addr } { dup "text" $= { drop @next serialize-text } { "unknown record type "' swap $+ +"'" abort } cond } cond } cond } cond } : parse-value { @next dup "owner" $= { drop -2 cl-parse-smc-addr serialize-smc-addr } { dup "cat" $= { drop parse-cat-num parse-value } { "unknown action '" swap $+ +"'" abort } cond } cond register-value } : parse-action { { @end? not } { parse-action } while } : parse-actions parse-actions // ( S -- S1 .. Sn n ) { 1 swap { dup "." $pos dup 0>= } { $| 1 $| nip rot 1+ swap } while drop swap } : split-by-dots // ( S -- s ) { dup $len dup 0= abort"subdomain cannot be empty" 126 > abort"subdomain too long" dup 0 chr $pos 1+ abort"subdomain contains null characters" split-by-dots s main-op ( _( `add 0x72656764 ) _( `update 0x75706464 ) _( `prolong 0x70726f6c ) ) assq-val not abort"unknown main operation" =: op-id ."Automatic DNS smart contract address = " dest-addr 2dup .addr cr 6 .Addr cr ."Action: " main-op .l subdomain type space expire-at . cr ."Operation code: 0x" op-id 8 0X. cr ."Value: " Values @ dup null? { drop ."(none)" } { =: actions-builder // create an internal message now 32 << actions-builder hashu 32 1<<1- and + =: query_id s tuck sbits 8 / 7 i, swap s, main-op `prolong eq? { Values @ ref, } ifnot expire-at 32 u, b> dup ."Internal message body is: " B dup Bx. cr ."Query_id is " query_id dup . ."= 0x" X. cr savefile tuck B>file ."(Saved to file " type .")" cr