merge master in

This commit is contained in:
akcodez
2025-09-24 09:26:55 -07:00
205 changed files with 11259 additions and 744 deletions

View File

@@ -4,6 +4,7 @@
[AMMオブジェクト]: /@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/amm.md [AMMオブジェクト]: /@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/amm.md
[AMMBid]: /@l10n/ja/docs/references/protocol/transactions/types/ammbid.md [AMMBid]: /@l10n/ja/docs/references/protocol/transactions/types/ammbid.md
[AMMBidトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammbid.md [AMMBidトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammbid.md
[AMMClawbackトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammclawback.md
[AMMCreate]: /@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md [AMMCreate]: /@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md
[AMMCreateトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md [AMMCreateトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/ammcreate.md
[AMMDelete]: /@l10n/ja/docs/references/protocol/transactions/types/ammdelete.md [AMMDelete]: /@l10n/ja/docs/references/protocol/transactions/types/ammdelete.md
@@ -148,6 +149,7 @@
[PermissionDelegation amendment]: /@l10n/ja/resources/known-amendments.md#permissiondelegation [PermissionDelegation amendment]: /@l10n/ja/resources/known-amendments.md#permissiondelegation
[PermissionedDEX amendment]: /@l10n/ja/resources/known-amendments.md#permissioneddex [PermissionedDEX amendment]: /@l10n/ja/resources/known-amendments.md#permissioneddex
[PermissionedDomains amendment]: /@l10n/ja/resources/known-amendments.md#permissioneddomains [PermissionedDomains amendment]: /@l10n/ja/resources/known-amendments.md#permissioneddomains
[PermissionedDomainSetトランザクション]: /@l10n/ja/docs/references/protocol/transactions/types/permissioneddomainset.md
[許可型ドメイン]: /@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md [許可型ドメイン]: /@l10n/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains.md
[PriceOracle amendment]: /@l10n/ja/resources/known-amendments.md#priceoracle [PriceOracle amendment]: /@l10n/ja/resources/known-amendments.md#priceoracle
[MPTokensV1_1 amendment]: /@l10n/ja/resources/known-amendments.md#priceoracle [MPTokensV1_1 amendment]: /@l10n/ja/resources/known-amendments.md#priceoracle
@@ -173,7 +175,7 @@
[通貨額の指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#通貨額の指定 [通貨額の指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#通貨額の指定
[レジャーの指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#レジャーの指定 [レジャーの指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#レジャーの指定
[時間の指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#時間の指定 [時間の指定]: /@l10n/ja/docs/references/protocol/data-types/basic-data-types.md#時間の指定
[Specifying Without Amounts]: /@l10n/ja/docs/references/protocol/data-types/currency-formats.md#specifying-without-amounts [金額なしの指定]: /@l10n/ja/docs/references/protocol/data-types/currency-formats.md#金額なしでの通貨の指定
[SusPay amendment]: /@l10n/ja/resources/known-amendments.md#suspay [SusPay amendment]: /@l10n/ja/resources/known-amendments.md#suspay
[TickSize amendment]: /@l10n/ja/resources/known-amendments.md#ticksize [TickSize amendment]: /@l10n/ja/resources/known-amendments.md#ticksize
[Ticketエントリ]: /@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/ticket.md [Ticketエントリ]: /@l10n/ja/docs/references/protocol/ledger-data/ledger-entry-types/ticket.md

View File

@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg fill-opacity="1" xmlns:xlink="http://www.w3.org/1999/xlink" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" width="630" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 630 460" height="460" xmlns="http://www.w3.org/2000/svg" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto"
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
/><g
><defs id="defs1"
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath1"
><path d="M0 0 L2147483647 0 L2147483647 2147483647 L0 2147483647 L0 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath2"
><path d="M0 0 L0 140 L160 140 L160 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath3"
><path d="M0 0 L0 140 L200 140 L200 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath4"
><path d="M0 0 L0 140 L190 140 L190 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath5"
><path d="M0 0 L0 80 L140 80 L140 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath6"
><path d="M0 0 L0 40 L110 40 L110 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath7"
><path d="M0 0 L0 30 L120 30 L120 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath8"
><path d="M0 0 L0 180 L270 180 L270 0 Z"
/></clipPath
></defs
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(450,300)" stroke-opacity="0" stroke="rgb(255,255,255)"
><circle r="7" clip-path="url(#clipPath2)" cx="80.5" cy="7.5" stroke="none"
/></g
><g transform="translate(450,300)"
><circle fill="none" r="7" clip-path="url(#clipPath2)" cx="80.5" cy="7.5"
/><path fill="none" d="M59.5 21.5 L101.5 21.5" clip-path="url(#clipPath2)"
/><path fill="none" d="M80.5 14.5 L80.5 42.5" clip-path="url(#clipPath2)"
/><path fill="none" d="M80.5 42.5 L66.5 70.5" clip-path="url(#clipPath2)"
/><path fill="none" d="M80.5 42.5 L94.5 70.5" clip-path="url(#clipPath2)"
/><text x="60" font-size="14px" y="93.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>Tracy</text
><text x="25" font-size="14px" y="109.2188" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>(許可型DEXの</text
><text x="33" font-size="14px" y="125.3281" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>トレーダー)</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(20,20)" stroke-opacity="0" stroke="rgb(255,255,255)"
><rect x="0.5" width="198.5" height="138.5" y="0.5" clip-path="url(#clipPath3)" stroke="none"
/></g
><g transform="translate(20,20)"
><rect fill="none" x="0.5" width="198.5" height="138.5" y="0.5" clip-path="url(#clipPath3)"
/><text x="60" font-size="14px" y="18.1094" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="11" font-size="14px" y="34.2188" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>USD.Acme:FOO.WayGate</text
><path fill="none" d="M1 40.2188 L199 40.2188" clip-path="url(#clipPath3)"
/><text x="5" font-size="14px" y="55.3281" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" font-weight="bold" xml:space="preserve"
>DomainID: ドメインA</text
><path fill="none" d="M1 61.3281 L199 61.3281" clip-path="url(#clipPath3)"
/><text x="5" font-size="14px" y="76.4375" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>10 FOO : 10 USD Marko</text
><path fill="none" d="M1 82.4375 L199 82.4375" clip-path="url(#clipPath3)"
/><text x="5" font-size="14px" y="97.5469" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>9 FOO : 15 USD Tracy</text
><path fill="none" d="M1 103.5469 L199 103.5469" clip-path="url(#clipPath3)"
/><text x="5" font-size="14px" y="118.6562" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>...</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(290,60)" stroke-opacity="0" stroke="rgb(255,255,255)"
><rect x="0.5" width="188.5" height="138.5" y="0.5" clip-path="url(#clipPath4)" stroke="none"
/></g
><g transform="translate(290,60)"
><rect fill="none" x="0.5" width="188.5" height="138.5" y="0.5" clip-path="url(#clipPath4)"
/><text x="60" font-size="14px" y="18.1094" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
>ドメインA</text
><path fill="none" d="M1 24.1094 L189 24.1094" clip-path="url(#clipPath4)"
/><text x="5" font-size="14px" y="39.2188" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
>所有者: Owen</text
><text x="5" font-size="14px" y="55.3281" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
>承認された資格情報:</text
><text x="5" font-size="14px" y="71.4375" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
>- "認可済" by Isabel</text
><text x="5" font-size="14px" y="87.5469" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
></text
><text x="5" font-size="14px" y="103.6562" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" font-weight="bold" xml:space="preserve"
>- "認可済" by Owen</text
><text x="5" font-size="14px" y="119.7656" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" font-weight="bold" xml:space="preserve"
></text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(120,300)" stroke-opacity="0" stroke="rgb(255,255,255)"
><circle r="7" clip-path="url(#clipPath2)" cx="80.5" cy="7.5" stroke="none"
/></g
><g transform="translate(120,300)"
><circle fill="none" r="7" clip-path="url(#clipPath2)" cx="80.5" cy="7.5"
/><path fill="none" d="M59.5 21.5 L101.5 21.5" clip-path="url(#clipPath2)"
/><path fill="none" d="M80.5 14.5 L80.5 42.5" clip-path="url(#clipPath2)"
/><path fill="none" d="M80.5 42.5 L66.5 70.5" clip-path="url(#clipPath2)"
/><path fill="none" d="M80.5 42.5 L94.5 70.5" clip-path="url(#clipPath2)"
/><text x="60" font-size="14px" y="93.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>Owen</text
><text x="19" font-size="14px" y="109.2188" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>(資格情報の発行者</text
><text x="11" font-size="14px" y="125.3281" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>かつドメインの所有者)</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(300,290)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L80.7725 0.5 L80.7725 21.6094 L139 21.6094 L139 79 L0.5 79 Z" stroke="none" clip-path="url(#clipPath5)"
/></g
><g transform="translate(300,290)"
><path fill="none" d="M0.5 0.5 L80.7725 0.5 L80.7725 21.6094 L139 21.6094 L139 79 L0.5 79 Z" clip-path="url(#clipPath5)"
/><path fill="none" d="M0.5 21.6094 L80.7725 21.6094" clip-path="url(#clipPath5)"
/><text x="5" font-size="14px" y="16.1094" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" xml:space="preserve"
>資格情報</text
><text x="5" font-size="14px" y="39.5" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" xml:space="preserve"
>タイプ: "認可済"</text
><text x="5" font-size="14px" y="55.6094" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" xml:space="preserve"
>発行者: Owen</text
><text x="5" font-size="14px" y="71.7188" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" xml:space="preserve"
>対象: Tracy</text
></g
><g stroke-dasharray="8,5" stroke-miterlimit="5" transform="translate(430,310)" stroke-linecap="butt"
><path fill="none" d="M90.5 20.5 L11.5 20.5" clip-path="url(#clipPath6)"
/><path fill="white" d="M22.2583 14 L11 20.5 L22.2583 27 Z" clip-path="url(#clipPath6)" stroke="none"
/><path fill="none" stroke-miterlimit="10" stroke-dasharray="none" d="M22.2583 14 L11 20.5 L22.2583 27 Z" clip-path="url(#clipPath6)" stroke-linecap="square"
/></g
><g font-family="sans-serif" font-size="14px" transform="translate(430,310)"
><text x="32.2207" xml:space="preserve" y="16" clip-path="url(#clipPath6)" stroke="none"
>保有</text
></g
><g stroke-dasharray="8,5" stroke-miterlimit="5" transform="translate(190,60)" stroke-linecap="butt"
><path fill="none" d="M99.5 10.5 L10.5 10.5" clip-path="url(#clipPath7)"
/><path fill="white" d="M88.7417 4 L100 10.5 L88.7417 17 Z" clip-path="url(#clipPath7)" stroke="none"
/><path fill="none" stroke-miterlimit="10" stroke-dasharray="none" d="M88.7417 4 L100 10.5 L88.7417 17 Z" clip-path="url(#clipPath7)" stroke-linecap="square"
/></g
><g stroke-dasharray="8,5" stroke-miterlimit="5" transform="translate(170,150)" stroke-linecap="butt"
><path fill="none" d="M10.5 11.5 L10.5 40.5" clip-path="url(#clipPath8)"
/><path fill="none" d="M10.5 40.5 L230.5 40.5" clip-path="url(#clipPath8)"
/><path fill="none" d="M230.5 40.5 L230.5 150.5" clip-path="url(#clipPath8)"
/><path fill="none" d="M230.5 150.5 L250.5 160.5" clip-path="url(#clipPath8)"
/><path fill="white" d="M4 22.2583 L10.5 11 L17 22.2583 Z" clip-path="url(#clipPath8)" stroke="none"
/><path fill="none" stroke-miterlimit="10" stroke-dasharray="none" d="M4 22.2583 L10.5 11 L17 22.2583 Z" clip-path="url(#clipPath8)" stroke-linecap="square"
/></g
><g font-family="sans-serif" font-size="14px" transform="translate(170,150)"
><text x="14" xml:space="preserve" y="55.2188" clip-path="url(#clipPath8)" stroke="none"
>アクセス許可</text
></g
><g stroke-dasharray="8,5" stroke-miterlimit="5" transform="translate(210,310)" stroke-linecap="butt"
><path fill="none" d="M89.5 20.5 L10.5 20.5" clip-path="url(#clipPath6)"
/><path fill="white" d="M78.7417 14 L90 20.5 L78.7417 27 Z" clip-path="url(#clipPath6)" stroke="none"
/><path fill="none" stroke-miterlimit="10" stroke-dasharray="none" d="M78.7417 14 L90 20.5 L78.7417 27 Z" clip-path="url(#clipPath6)" stroke-linecap="square"
/></g
><g font-family="sans-serif" font-size="14px" transform="translate(210,310)"
><text x="29.3696" xml:space="preserve" y="16" clip-path="url(#clipPath6)" stroke="none"
>発行</text
></g
></g
></svg
>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg fill-opacity="1" xmlns:xlink="http://www.w3.org/1999/xlink" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" width="810" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 10 810 330" height="330" xmlns="http://www.w3.org/2000/svg" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto"
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
/><g
><defs id="defs1"
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath1"
><path d="M0 0 L2147483647 0 L2147483647 2147483647 L0 2147483647 L0 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath2"
><path d="M0 0 L0 70 L110 70 L110 0 Z"
/></clipPath
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath3"
><path d="M0 0 L0 290 L250 290 L250 0 Z"
/></clipPath
></defs
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(670,240)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(670,240)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="27" font-size="14px" y="42.5547" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>EUR:JPY</text
><text x="10" font-size="14px" y="58.6641" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>DomainID: B</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(550,240)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(550,240)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="27" font-size="14px" y="42.5547" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>JPY:EUR</text
><text x="10" font-size="14px" y="58.6641" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>DomainID: B</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(280,30)" stroke-opacity="0" stroke="rgb(255,255,255)"
><rect x="0.5" width="248.5" height="288.5" y="0.5" clip-path="url(#clipPath3)" stroke="none"
/></g
><g stroke-dasharray="8,5" stroke-miterlimit="5" transform="translate(280,30)" stroke-linecap="butt"
><rect fill="none" x="0.5" width="248.5" height="288.5" y="0.5" clip-path="url(#clipPath3)"
/><text x="54" font-size="14px" y="18.1094" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>許可型DEX A</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(30,160)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(30,160)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="22" font-size="14px" y="50.6094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>USD:FOO</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(30,240)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(30,240)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="23" font-size="14px" y="50.6094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>BAR:BAZ</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(150,160)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(150,160)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="22" font-size="14px" y="50.6094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>FOO:USD</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(150,80)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(150,80)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="23" font-size="14px" y="50.6094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>FOO:XRP</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(30,80)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(30,80)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="23" font-size="14px" y="50.6094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>XRP:FOO</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(20,30)" stroke-opacity="0" stroke="rgb(255,255,255)"
><rect x="0.5" width="248.5" height="288.5" y="0.5" clip-path="url(#clipPath3)" stroke="none"
/></g
><g stroke-dasharray="8,5" stroke-miterlimit="5" transform="translate(20,30)" stroke-linecap="butt"
><rect fill="none" x="0.5" width="248.5" height="288.5" y="0.5" clip-path="url(#clipPath3)"
/><text x="89" font-size="14px" y="18.1094" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オープンDEX</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(410,240)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(410,240)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="27" font-size="14px" y="42.5547" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>EUR:JPY</text
><text x="11" font-size="14px" y="58.6641" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>DomainID: A</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(290,160)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(290,160)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="22" font-size="14px" y="42.5547" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>USD:FOO</text
><text x="11" font-size="14px" y="58.6641" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>DomainID: A</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(410,80)" stroke-opacity="0" stroke="rgb(255,255,255)"
><path d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" stroke="none" clip-path="url(#clipPath2)"
/></g
><g transform="translate(410,80)"
><path fill="none" d="M0.5 0.5 L88.998 0.5 L88.998 21.6094 L109 21.6094 L109 69 L0.5 69 Z" clip-path="url(#clipPath2)"
/><path fill="none" d="M0.5 21.6094 L88.998 21.6094" clip-path="url(#clipPath2)"
/><text x="5" font-size="12px" y="16.1094" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>オーダーブック</text
><text x="23" font-size="14px" y="42.5547" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>FOO:XRP</text
><text x="11" font-size="14px" y="58.6641" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" xml:space="preserve"
>DomainID: A</text
></g
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(540,30)" stroke-opacity="0" stroke="rgb(255,255,255)"
><rect x="0.5" width="248.5" height="288.5" y="0.5" clip-path="url(#clipPath3)" stroke="none"
/></g
><g stroke-dasharray="8,5" stroke-miterlimit="5" transform="translate(540,30)" stroke-linecap="butt"
><rect fill="none" x="0.5" width="248.5" height="288.5" y="0.5" clip-path="url(#clipPath3)"
/><text x="54" font-size="14px" y="18.1094" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" xml:space="preserve"
>許可型DEX B</text
></g
></g
></svg
>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,113 @@
---
seo:
description: 許可型メインインスタンスの定義と詳細について
labels:
- コンプライアンス
- 分散型取引所
---
# 許可型DEX
許可型DEXは、XRP Ledgerの[分散型取引所(DEX)](./index.md)内での取引を制御する環境です。許可型DEXでの取引は、オープンDEXと同様ですが、[_許可型ドメイン_](./permissioned-domains.md)によって誰がオファーを置くことができるか、またはオファーを受け入れることができるかを制御します。許可型DEXを利用することで、規制下にある企業はXRP Ledgerでの取引に参加し、取引先のすべての相手方が適切に検証されていることを確認することができます。
XRP Ledgerブロックチェーン内には、複数の許可型DEXが存在することができます。それぞれは、許可型ドメインと関連付けられており、そのDEXへのアクセスを許可するリストとして機能します。許可型DEX内に置かれた取引は、同じ許可型DEX内の他の取引にのみ実行できます。各許可型DEXは、必要に応じて、任意の数の通貨ペアの注文帳を持つことができます。
## 背景: 許可型DEXの必要性
XRP Ledgerは、ローンチ以来、単一の、_オープンDEX_ を持っています。XRPLアカウントを持っていれば誰でもこのDEXで取引することができ、システムは誰がオファーを作成したに関係なく、マッチングする注文、もしくはオファーを自動的に約定します。注文はまた、クロスカレンシー支払いに流動性を提供し、潜在的に1つのアトミック取引の一部として複数の取引を実行することができます。
システムは、アカウントの背後にある人々や組織について何も知らないため、ある取引の相手方が誰かは確実ではありません。しかし、経済制裁や金融規制は、犯罪者、テロリスト、または特定の国との取引に対して厳格なルールを課しています。これらの制限により、規制下にある金融機関は、オープンDEXでの取引に対するリスクを負うことを望んでいないかもしれません。
さらなる背景情報:
- [分散型取引所](./index.md)
- [オファー](./offers.md)
- [許可型ドメイン](./permissioned-domains.md)
## 許可型DEXの重要な役割
許可型DEXを使用するには、以下の役割と責任を持つ参加者が必要です。
- 少なくとも2人のトレーダーがマッチングするオファーを置く必要があります。例えば、1人がXRPをUSDに交換し、もう1人がUSDをXRPに交換します。
- 許可型ドメインの所有者。許可型ドメインへのアクセスを許可する資格情報を制御します。
- 資格情報(Credentials)の発行者。許可型ドメインへのアクセスを許可する資格情報を発行します。
1つのアカウントがこれらの役割のいずれかを複数回果たすことができます。例えば、許可型ドメインの所有者、資格情報の発行者、およびトレーダーの3つの役割を同時に果たすことができます。唯一の制限は、トレーダーが異なるアカウントである必要があることです。
{% inline-svg file="./permissioned-dex-roles.svg" /%}
_図: 許可型オーダーブック。Owenは許可型ドメインの所有者であり、許可型ドメインの承認された資格情報の1つの発行者です。TracyはOwenが発行した適切な資格情報を保有しているため、許可型オーダーブックで取引することができます。_
## 許可型DEXの構造を理解する: オファーの種類と相互作用
許可型DEX機能を使用すると、取引オファーは _オープン_、_許可型_、または _ハイブリッド_ のいずれかになります。
### オープンオファー
オープンオファーはオープンDEXを使用し、他のオープンなオファー、ハイブリッドなオファー、[自動マーケットメーカー(AMM)](./automated-market-makers.md)、またはオファーとAMMの組み合わせによってマッチングすることができます。_オープンオファー_ は、許可型DEXがない場合のXRPLのDEXの動作と変わりません。
### 許可型オファー
許可型オファーはドメインIDを指定し、そのドメインIDに一致する許可型ドメインが存在し、オファーを置いたアカウントがそのドメインにアクセスできる場合にのみ有効です。許可型オファーは、指定されたドメインと通貨ペアのオーダーブックに配置され、オープンDEXのオーダーブックとは別です。
許可型オファーは、同じドメインIDを指定する許可型オファーとのみマッチングすることができます。[クロスカレンシー支払い](../../payment-types/cross-currency-payments.md)もドメインIDを指定することができ、その場合は、対応する許可型DEXからのみオファーを約定するように制限されます。許可型DEX内の取引は、必要な注文がすべて同じ許可型DEX内に存在する限り、[オートブリッジング](./autobridging.md)を使用することができます。
### ハイブリッドオファー
ハイブリッドオファーはドメインIDを指定し、ハイブリッドフラグを付けます。許可型オファーと同様に、指定された許可型ドメインが存在し、オファーを置いたアカウントがそのドメインにアクセスできる場合にのみ有効です。ただし、ハイブリッドオファーは、指定されたDEXとオープンDEXの両方でオファーをマッチングすることができます。
ハイブリッドオファーは、オープンDEXのオーダーブックと、その通貨ペアの許可型ドメイン固有のオーダーブックの両方で追跡され、どちらかのオファーとマッチングすることができます。配置された場合、許可型DEXのオファーと優先的にマッチングします。
### オープン、ハイブリッド、許可型オファーのマッチング方法
要約すると、以下の表に、どのオファーがマッチングできるかをまとめています:
| オファー/支払いタイプ | オープンオファー | ハイブリッドオファー | 許可型オファー | AMM |
|-----------------------|------------------|----------------------|-------------------|-----|
| オープン | ✅ | ✅ | ❌ | ✅ |
| ハイブリッド | ✅ | ✅ | ✅ (同じドメイン) | ✅ |
| 許可型 | ❌ | ❌ | ✅ (同じドメイン) | ❌ |
許可型DEXを表すための単一のレジャーエントリはありません。 それは暗黙的に、同じドメインIDを持つすべてのオーダーブックとして存在します。指定されたドメインIDを使用して有効なオファーが配置されると、そのオーダーブックが作成され、空になると自動的に削除されます。
1つのトランザクションは、同じドメインIDを持つ複数のオーダーブックを使用できます。つまり、同じ許可型DEX内の異なる通貨ペアです。それは、長い[クロスカレンシー支払い](../../payment-types/cross-currency-payments.md)の一部として、またはオートブリッジングを介して使用することができます。ハイブリッドオファーは、許可型オファーとオープンオファーの混合をマッチングすることができますが、トランザクションは複数の異なるドメインを使用することはできません。
どのDEXでも利用可能な流動性の量と最良の交換レートは、そのDEXに配置されたオファーによって異なる場合があります。一部のトレーダーは、価格差を利用するために複数の許可型DEXとオープンDEXで取引することを選択するかもしれませんが、他のトレーダーは、そのコンプライアンス要件に応じて、1つのドメインで厳密に取引するかもしれません。
{% inline-svg file="./permissioned-dex-structure.svg" /%}
_図: オープンDEXと2つの異なる許可型DEX。それぞれが、可能な通貨ペアのサブセットの注文帳を含んでいます。_
### 無効な許可型オファー
オープンDEXでオファーが資金不足になる方法に加えて、許可型DEXでのオファーは _無効_ になる可能性があります。無効なオファーは、資金不足のオファーと同じ方法で処理され、トランザクションがそれらを含むオーダーブックを変更するたびに自動的に削除されます。トランザクションがそれらを削除するまで、レジャーデータ内に無期限に残ることができますが、無効な場合は約定できません。
許可型オファーが無効になる理由には、以下のようなものがあります。
- オファーを置いたアカウントが保有する資格情報が期限切れまたは削除された。
- 許可型ドメインが更新され、アクセスを許可する資格情報のセットが変更され、オファーを置いたアカウントが新しい資格情報を保有していない。
- 許可型ドメインが削除された。
資金不足のオファーと同様に、オファーが一時的に無効になり、再度有効になる可能性があります。例えば、トレーダーの資格情報が許可型ドメインへのアクセスを許可する資格情報が期限切れになった場合、そのトレーダーの許可型DEXでのオファーは無効になります。しかし、資格情報が更新された場合、すでに削除されていないオファーは自動的に有効になります。
### 許可型DEXの制限
許可型DEX機能は、**PermissionedDEX** Amendmentによって有効になり、[Credentials](../../decentralized-storage/credentials.md)と[Permissioned Domains](./permissioned-domains.md) Amendmentに依存しているため、それらのAmendmentが _すべて_ 有効になるまで利用できません。
#### AMMとの互換性なし
許可型DEXは、[自動マーケットメーカー(AMM)](../../tokens/decentralized-exchange/automated-market-makers.md)と互換性がありません。許可型オファーと許可型支払いはAMMで約定できません。また、許可型ドメインによってAMMへのアクセスを制限することはできません。オープンDEXを使用する取引は、場合によってはハイブリッドオファーを消費し、同じトランザクションでAMMを使用することができますが、ドメインを指定するトランザクションではAMMを使用することはできません。
**許可型DEXは独立しています**
許可型DEXは独立しており、それぞれが独自のオーダーブックとオファーを持っています。1つのトランザクションは、複数の許可型DEXで取引することはできません。また、複数の許可型DEXから流動性を集約することはできません。ハイブリッドオファーは、1つの許可型DEXとオープンDEXの両方を使用することができますが、複数の異なる許可型DEXを使用することはできません。
#### 許可型DEXのセキュリティに関する考慮事項
許可型DEXのセキュリティと公平性は、許可型ドメインの所有者と、そのドメインへのアクセスを許可する資格情報の発行者に依存します。基本的に、各資格情報の定義とその資格情報を取得するための要件は、資格情報の発行者によって定義され、適用されているため、許可型ドメインの存在は、実際に誰がそれを使用できるかについて、本質的に何も意味しません。
資格情報の発行者は、資格情報を発行または取り消すことができます。もし、それらが信頼できないか、侵害されている場合、それらの資格情報を受け入れる許可型ドメインも同様です。同様に、ドメインの所有者は、ドメインの承認された資格情報のリストを変更して、ドメインへのアクセスを許可または拒否することができるため、もし、それらが信頼できないか、侵害されている場合、ドメインも同様です。

View File

@@ -36,4 +36,4 @@ _([PermissionedDomains amendment][]が必要です {% not-enabled /%})_
- 単一資産Vaultと貸付プロトコル - 単一資産Vaultと貸付プロトコル
- 許可型DEX - 許可型DEX
{% raw-partial file="/docs/_snippets/common-links.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -313,9 +313,6 @@ _**公開ハブを使用してバリデータをネットワークに接続す
4. 記入したGoogleフォームを送信すると、ドメイン検証の成否を通知するメールがXRP Chartsから送信されます。ドメイン検証が成功した場合は、XRP Chartsの[バリデータレジストリー](https://xrpcharts.ripple.com/#/validators)にバリデータとドメインが表示されます。 4. 記入したGoogleフォームを送信すると、ドメイン検証の成否を通知するメールがXRP Chartsから送信されます。ドメイン検証が成功した場合は、XRP Chartsの[バリデータレジストリー](https://xrpcharts.ripple.com/#/validators)にバリデータとドメインが表示されます。
<!--{ ***TODO: For the future - add a new section or separate document: "Operating a Trusted Validator" -- things that you need to be aware of once your validator has been added to a UNL and is participating in consensus. We should tell the user what to expect once they are listed in a UNL. How to tell if your validator is participating in the consensus process? How to tell if something isn't right with your validator - warning signs that they should look out for? How to tell if your validator has fallen out of agreement - what is the acceptable vs unacceptable threshold? Maybe provide a script that will alert them when something is going wrong.*** }-->
## バリデータキーの破棄 ## バリデータキーの破棄

View File

@@ -119,7 +119,7 @@ rippled json ledger_entry '{ "index": "7DB0788C020F02780A673DC74757F23823FA3014C
アドレスから[AccountRootエントリ](../../../protocol/ledger-data/ledger-entry-types/accountroot.md)を取得します。これは[account_infoメソッド][]とほぼ同じです。 アドレスから[AccountRootエントリ](../../../protocol/ledger-data/ledger-entry-types/accountroot.md)を取得します。これは[account_infoメソッド][]とほぼ同じです。
| フィールド | 型 | 説明 | | フィールド | 型 | 説明 |
|:----------- ---|:--------------------|:----------------------| |:---------------|:--------------------|:----------------------|
| `account_root` | 文字列 - [アドレス][] | 取得する[AccountRootエントリ](../../../protocol/ledger-data/ledger-entry-types/accountroot.md)の標準アドレス。 | | `account_root` | 文字列 - [アドレス][] | 取得する[AccountRootエントリ](../../../protocol/ledger-data/ledger-entry-types/accountroot.md)の標準アドレス。 |
{% tabs %} {% tabs %}

View File

@@ -1,6 +1,4 @@
--- ---
html: book_offers.html
parent: path-and-order-book-methods.html
seo: seo:
description: オーダーブックと呼ばれる、2つの通貨間のオファーのリストを取得します。 description: オーダーブックと呼ばれる、2つの通貨間のオファーのリストを取得します。
labels: labels:
@@ -10,7 +8,7 @@ labels:
# book_offers # book_offers
[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/ripple/rpc/handlers/BookOffers.cpp "Source") [[ソース]](https://github.com/XRPLF/rippled/blob/master/src/ripple/rpc/handlers/BookOffers.cpp "Source")
`book_offers`メソッドは、[オーダーブック](http://www.investopedia.com/terms/o/order-book.asp)と呼ばれる、2つの通貨間のオファーのリストを取得します。結果が非常に大きい場合、結果の一部がマーカー付きで返されます。これにより、その後のリクエストは前回のリクエストで終わった箇所から再開できます。 `book_offers`メソッドは、2つの通貨間の[オファー](../../../../concepts/tokens/decentralized-exchange/offers.md)のリストを取得します。これは、_オーダーブック_ とも呼ばれます。レスポンスは、[資金供給のないオファー](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーのライフサイクル)を省略し、残りの各オファーの合計に対して資金供給されている割合を報告します。
## リクエストのフォーマット ## リクエストのフォーマット
リクエストのフォーマットの例: リクエストのフォーマットの例:
@@ -69,15 +67,16 @@ rippled book_offers 'USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' 'EUR/rvYAfWj5gh67oV6
リクエストには以下のパラメーターが含まれます。 リクエストには以下のパラメーターが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 必須? | 説明 |
|:---------------|:-------------------------------------------|:-------------------------------| |:---------------|:-------------------------|:-------|:-------------------------------|
| `ledger_hash` | 文字列 | _省略可_ 使用するレジャーバージョンの20バイトの16進文字列。[レジャーの指定][]をご覧ください) | | `taker_gets` | オブジェクト | はい | オファーを受諾するアカウントが受け取る通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定しますXRPの場合はissuerを省略 |
| `ledger_index` | 文字列または符号なし整数 | _省略可_ 使用するレジャーの[レジャーインデックス][]、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください) | | `taker_pays` | オブジェクト | はい | オファーを受諾するアカウントが支払う通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定しますXRPの場合はissuerを省略 |
| `limit` | 符号なし整数 | _省略可_ 指定されている場合、サーバはこの制限を超える数のオファーを結果に含めません。資金供給のないオファーはサーバにより省略されるため、返される結果の総数はこの制限よりも少ないことがあります。 | | `domain` | [ハッシュ][] | いいえ | 許可型ドメインのレジャーエントリID。指定された場合、オープンDEXの代わりに、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)からオファーを返します。 _([PermissionedDEX amendment][]が必要です。 {% not-enabled /%})_ |
| `marker` | [マーカー][] | _省略可_ 以前にページネーションされたレスポンスの値。そのレスポンスを停止した箇所からデータの取得を再開します。 | | `ledger_hash` | [ハッシュ][] | いいえ | 使用するレジャーバージョンの20バイトの16進文字列。[レジャーの指定][]をご覧ください) |
| `taker` | 文字列 | _省略可_ パースペクティブとして使用するアカウントの[アドレス][]。このアカウントが発行した[資金供給のないオファー](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーのライフサイクル)は常にレスポンスに含まれます。(これを使用して、キャンセルしたい各自のオーダーを検索できます。 | | `ledger_index` | [レジャーインデックス][] | いいえ | 使用するレジャーの[レジャーインデックス][]、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください |
| `taker_gets` | オブジェクト | オファーを受諾するアカウントが受け取る通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定しますXRPの場合はissuerを省略。 | | `limit` | 整数 | いいえ | 指定されている場合、サーバはこの制限を超える数のオファーを結果に含めません。資金供給のないオファーはサーバにより省略されるため、返される結果の総数はこの制限よりも少ないことがあります。 |
| `taker_pays` | オブジェクト | オファーを受諾するアカウントが支払う通貨を、[通貨額][通貨額]と同様に、`currency`フィールドと`issuer`フィールドを持つオブジェクトとして指定しますXRPの場合はissuerを省略 | | `taker` | 文字列 | いいえ | パースペクティブとして使用するアカウントの[アドレス][]。このアカウントが発行した[資金供給のないオファー](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーのライフサイクル)は常にレスポンスに含まれます。(これを使用して、キャンセルしたい各自のオーダーを検索できます。) |
## レスポンスのフォーマット ## レスポンスのフォーマット
@@ -161,26 +160,97 @@ rippled book_offers 'USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' 'EUR/rvYAfWj5gh67oV6
``` ```
{% /tab %} {% /tab %}
{% tab label="Commandline" %}
```json
{
"result" : {
"ledger_current_index" : 56867201,
"offers" : [
{
"Account" : "rnixnrMHHvR7ejMpJMRCWkaNrq3qREwMDu",
"BookDirectory" : "7E5F614417C2D0A7CEFEB73C4AA773ED5B078DE2B5771F6D56038D7EA4C68000",
"BookNode" : "0000000000000000",
"Flags" : 131072,
"LedgerEntryType" : "Offer",
"OwnerNode" : "0000000000000000",
"PreviousTxnID" : "E43ADD1BD4AC2049E0D9DE6BC279B7FD95A99C8DE2C4694A4A7623F6D9AAAE29",
"PreviousTxnLgrSeq" : 47926685,
"Sequence" : 219,
"TakerGets" : {
"currency" : "EUR",
"issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value" : "2.459108753792364"
},
"TakerPays" : {
"currency" : "USD",
"issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value" : "24.59108753792364"
},
"index" : "3087B4828C6B5D8595EA325D69C0F396C57452893647799493A38F2C164990AB",
"owner_funds" : "2.872409153061363",
"quality" : "10"
},
{
"Account" : "rKwjWCKBaASEvtHCxtvReNd2i9n8DxSihk",
"BookDirectory" : "7E5F614417C2D0A7CEFEB73C4AA773ED5B078DE2B5771F6D56038D7EA4C68000",
"BookNode" : "0000000000000000",
"Flags" : 131072,
"LedgerEntryType" : "Offer",
"OwnerNode" : "0000000000000000",
"PreviousTxnID" : "B63B2ECD124FE6B02BC2998929517266BD221A02FEE51DDE4992C1BCB7E86CD3",
"PreviousTxnLgrSeq" : 43166305,
"Sequence" : 19,
"TakerGets" : {
"currency" : "EUR",
"issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value" : "3.52"
},
"TakerPays" : {
"currency" : "USD",
"issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value" : "35.2"
},
"index" : "89865F2C70D1140796D9D249AC2ED765AE2D007A52DEC6D6D64CCB1A77A6EB7F",
"owner_funds" : "3.523192614770459",
"quality" : "10",
"taker_gets_funded" : {
"currency" : "EUR",
"issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value" : "3.516160294182094"
},
"taker_pays_funded" : {
"currency" : "USD",
"issuer" : "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value" : "35.16160294182094"
}
}
],
"status" : "success",
"validated" : false
}
}
```
{% /tab %}
{% /tabs %} {% /tabs %}
このレスポンスは[標準フォーマット][]に従っており、正常に完了した場合は結果に次のフィールドが含まれます。 このレスポンスは[標準フォーマット][]に従っており、正常に完了した場合は結果に次のフィールドが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:-----------------------|:--------------------------|:------------------------| |:-----------------------|:-------------------------|:------------------------|
| `ledger_current_index` | 数値 - [レジャーインデックス][] | _`ledger_current_index`が指定されている場合は省略_ この情報の取得時に使用した、現在処理中のレジャーバージョンの[レジャーインデックス][]。 | | `ledger_current_index` | [レジャーインデックス][] | _(`ledger_current_index`が指定されている場合は省略)_ この情報の取得時に使用した、現在処理中のレジャーバージョンの[レジャーインデックス][]。 |
| `ledger_index` | 数値 - [レジャーインデックス][] | _`ledger_current_index`が指定されている場合は省略可)_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンのレジャーインデックス。 | | `ledger_index` | [レジャーインデックス][] | _(`ledger_current_index`が指定されている場合は省略)_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンのレジャーインデックス。 |
| `ledger_hash` | 文字列 - [ハッシュ][] | _省略される場合があります_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンの識別用ハッシュ。 | | `ledger_hash` | [ハッシュ][] | _省略される場合があります_ リクエストに従って、このデータの取得時に使用されたレジャーバージョンの識別用ハッシュ。 |
| `marker` | [マーカー][] | _省略される場合があります_ レスポンスがページネーションされていることを示す、サーバが定義した値。この値を次のコールに渡して、このコールで終わった箇所から再開します。この後に情報ページがない場合は省略されます。 | | `offers` | 配列 | Offerオブジェクトの配列。詳細は下記にて。 |
| `offers` | 配列 | Offerオブジェクトの配列。各オブジェクトには[Offer オブジェクト](../../../protocol/ledger-data/ledger-entry-types/offer.md)のフィールドが含まれています。 |
`offers`配列の要素には、Offerの標準フィールドの他に以下のフィールドが含まれます。 `offers`配列の要素には、[Offerエントリ][]の標準フィールドの他に以下の追加フィールドが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:--------------------|:---------------------------------|:--------------------| |:--------------------|:-----------|:--------------------|
| `owner_funds` | 文字列 | オファーの発行元が保有する取引可能なTakerGets通貨の金額。XRPはdrop単位で表されます。その他のすべての通貨は10進数値として表されます。1人のトレーダーの複数のオファーが同一のブックに含まれている場合、このフィールドは最高順位のオファーにのみ含まれます。 | | `owner_funds` | 文字列 | オファーの発行元が保有する取引可能なTakerGets通貨の金額。(XRPはdrop単位で表されます。その他のすべての通貨は10進数値として表されます。)1人のトレーダーの複数のオファーが同一のブックに含まれている場合、このフィールドは最高順位のオファーにのみ含まれます。 |
| `taker_gets_funded` | 文字列XRPまたはオブジェクトXRP以外 | 部分的に資金供給されているオファーのみに含まれますオファーの資金供給ステータスが指定されている場合に、受取人が受領できる最大通貨額。 | | `taker_gets_funded` | [通貨額][] | (部分的に資金供給されているオファーのみに含まれます) オファーの資金供給ステータスが指定されている場合に、受取人が受領できる最大通貨額。 |
| `taker_pays_funded` | 文字列XRPまたはオブジェクトXRP以外 | 部分的に資金供給されているオファーのみに含まれますオファーの資金供給ステータスが指定されている場合に、受取人が支払う最大通貨額。 | | `taker_pays_funded` | [通貨額][] | (部分的に資金供給されているオファーのみに含まれます) オファーの資金供給ステータスが指定されている場合に、受取人が支払う最大通貨額。 |
| `quality` | 文字列 | 為替レート`taker_pays``taker_gets`で割った比率。公正を期すため、同じクオリティのオファーは先入れ先出しで自動的に受諾されます。つまり、複数の人々が通貨を同じレートで取引するオファーを出した場合、最も古いオファーが最初に受諾されます。 | | `quality` | 文字列 | 為替レート(`taker_pays``taker_gets`で割った比率)。公正を期すため、同じクオリティのオファーは先入れ先出しで自動的に約定されます。(つまり、複数の人々が通貨を同じレートで取引するオファーを出した場合、最も古いオファーが最初に受諾されます。) |
## 考えられるエラー ## 考えられるエラー

View File

@@ -55,14 +55,15 @@ path_findコマンドには3種類のモードサブコマンドがあり
リクエストには以下のパラメーターが含まれます。 リクエストには以下のパラメーターが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 必須? | 説明 |
|:----------------------|:-----------------|:----------------------------------| |:----------------------|:-------------------------|:-------|:---------------------------|
| `subcommand` | 文字列 | `"create"`を使用してcreateサブコマンドを送信します。 | | `subcommand` | 文字列 | はい | `"create"`を使用してcreateサブコマンドを送信します。 |
| `source_account` | 文字列 | 索するパスの送金元アカウントの一意のアドレス。(つまり、支払いを送金するアカウントです。 | | `source_account` | 文字列 - [アドレス][] | はい | 索するパスの送金元アカウントのドレス。(つまり、支払いを送金するアカウント) |
| `destination_account` | 文字列 | 索するパスの送金先アカウントの一意のアドレス。(つまり、支払いを受領するアカウントです。 | | `destination_account` | 文字列 - [アドレス][] | はい | 索するパスの送金先アカウントのアドレス。(つまり、支払いを受領するアカウント) |
| `destination_amount` | 文字列またはオブジェクト | 送金先アカウントがトランザクションで受領する[通貨額][]。**特殊ケース:**{% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %}`value`フィールドには`"-1"`XRPの場合または-1XRP以外の通貨の場合を指定できます。これにより、最大限の額を送金できるパスがリクエストされます。ただし`send_max`指定されている場合は、指定額を上回る額が支払われることはありません。 | | `destination_amount` | [通貨額][] | はい | 送金先アカウントが受け取る金額。 **特殊ケース:** XRPの場合、`"-1"`を指定するか、トークンの場合、`value`フィールドの内容として-1を指定できます。これにより、`send_max`指定された金額を超えない範囲で、可能な限り多くの送金先への送金を要求します。 |
| `send_max` | 文字列またはオブジェクト | _省略可_ トランザクションに使用する[通貨額][]。`source_currencies`と同時に指定することはできません。{% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %} | | `domain` | 文字列 - [ハッシュ][] | いいえ | 許可型ドメインのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。 _([PermissionedDEX amendment][]が必要です。 {% not-enabled /%})_ |
| `paths` | 配列 | _省略可_ チェックする[ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を表すオブジェクトの配列。すでに判明している特定パスの変更内容を常に把握する場合や、特定パスに沿った支払いにかかる総コストを確認する場合にこのフィールドを使用できます。 | | `paths` | 配列 | いいえ | チェックする[支払いパス](../../../../concepts/tokens/fungible-tokens/paths.md)を表すオブジェクトの配列。すでに判明している特定パスの変更内容を常に把握する場合や、特定パスに沿った支払いにかかる総コストを確認する場合にこのフィールドを使用できます。 |
| `send_max` | [通貨額][] | いいえ | トランザクションに使用する[通貨額][]。`source_currencies`と同時に指定することはできません。|
サーバは`source_currencies`および`bridges`フィールドも認識しますが、これらのフィールドを使用した場合の結果は保証されません。これらのフィールドは将来のために予約されているものと考えてください。 サーバは`source_currencies`および`bridges`フィールドも認識しますが、これらのフィールドを使用した場合の結果は保証されません。これらのフィールドは将来のために予約されているものと考えてください。
@@ -444,8 +445,8 @@ path_findコマンドには3種類のモードサブコマンドがあり
この初期レスポンスは[標準フォーマット](../../api-conventions/response-formatting.md)に従っており、正常に完了した場合は次のフィールドが含まれています。 この初期レスポンスは[標準フォーマット](../../api-conventions/response-formatting.md)に従っており、正常に完了した場合は次のフィールドが含まれています。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:----------------------|:-----------------|:----------------------------------| |:----------------------|:-----------------|:---------------------------|
| `alternatives` | 配列 | 以下に説明する、提案される[パス](../../../../concepts/tokens/fungible-tokens/paths.md)のオブジェクトの配列。空の場合、送金元アカウントと送金先アカウントを結ぶパスが見つかりませんでした。 | | `alternatives` | 配列 | 以下に説明する、提案される[パス](../../../../concepts/tokens/fungible-tokens/paths.md)のオブジェクトの配列。空の場合、送金元アカウントと送金先アカウントを結ぶパスが見つかりませんでした。 |
| `destination_account` | 文字列 | トランザクションを受信するアカウントの一意のアドレス。 | | `destination_account` | 文字列 | トランザクションを受信するアカウントの一意のアドレス。 |
| `destination_amount` | 文字列またはオブジェクト | 送金先がトランザクションで受領する[通貨額][]。 | | `destination_amount` | 文字列またはオブジェクト | 送金先がトランザクションで受領する[通貨額][]。 |
@@ -455,8 +456,8 @@ path_findコマンドには3種類のモードサブコマンドがあり
`alternatives`配列の各要素は、1つの送金元通貨開始アカウントが保有から送金先アカウントへのパスと通貨を表すオブジェクトです。このオブジェクトのフィールドを次に示します。 `alternatives`配列の各要素は、1つの送金元通貨開始アカウントが保有から送金先アカウントへのパスと通貨を表すオブジェクトです。このオブジェクトのフィールドを次に示します。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:-----------------|:-----------------|:---------------------------------------| |:-----------------|:-----------------|:--------------------------------|
| `paths_computed` | 配列 | [ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を定義するオブジェクトの配列。 | | `paths_computed` | 配列 | [ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を定義するオブジェクトの配列。 |
| `source_amount` | 文字列またはオブジェクト | 送金先が必要な額を受領するために、送金元がこのパスで送金する必要がある[通貨額][]。 | | `source_amount` | 文字列またはオブジェクト | 送金先が必要な額を受領するために、送金元がこのパスで送金する必要がある[通貨額][]。 |
@@ -521,17 +522,17 @@ path_find createリクエストからの非同期フォローアップの例を
リクエストには以下のパラメーターが含まれます。 リクエストには以下のパラメーターが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:-------------|:-------|:-------------------------------------------| |:-------------|:-------|:------------------------------------|
| `subcommand` | 文字列 | closeサブコマンドを送信するため`"close"`を使用します。 | | `subcommand` | 文字列 | closeサブコマンドを送信するため`"close"`を使用します。 |
### レスポンスのフォーマット ### レスポンスのフォーマット
Pathfindingリクエストが正常にクローズされた場合、レスポンスは[`path_find create`](#path_find-create)に対する初期レスポンスと同じフォーマットであり、されに以下のフィールドが含まれます。 Pathfindingリクエストが正常にクローズされた場合、レスポンスは[`path_find create`](#path_find-create)に対する初期レスポンスと同じフォーマットであり、されに以下のフィールドが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:---------|:--------|:--------------------------------------------------------| |:-----------|:--------|:-------------------------------------------------|
| `closed` | ブール値 | 値が`true`の場合、これは`path_find close`コマンドに対するレスポンスです。 | | `closed` | ブール値 | 値が`true`の場合、これは`path_find close`コマンドに対するレスポンスです。 |
未処理のPathfindingリクエストがない場合はエラーが返されます。 未処理のPathfindingリクエストがない場合はエラーが返されます。
@@ -566,17 +567,17 @@ Pathfindingリクエストが正常にクローズされた場合、レスポン
リクエストには以下のパラメーターが含まれます。 リクエストには以下のパラメーターが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:-------------|:-------|:---------------------------------------------| |:-------------|:-------|:--------------------------------------|
| `subcommand` | 文字列 | `"status"`を使用して、statusサブコマンドを送信します。 | | `subcommand` | 文字列 | `"status"`を使用して、statusサブコマンドを送信します。 |
### レスポンスのフォーマット ### レスポンスのフォーマット
Pathfindingリクエストが実行中の場合、レスポンスは[`path_find create`](#path_find-create)に対する初期レスポンスと同じフォーマットであるのに加えて、以下のフィールドがあります。 Pathfindingリクエストが実行中の場合、レスポンスは[`path_find create`](#path_find-create)に対する初期レスポンスと同じフォーマットであるのに加えて、以下のフィールドがあります。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:---------|:--------|:--------------------------------------------------------| |:-----------|:--------|:-------------------------------------------------|
| `status` | ブール値 | 値が`true`の場合、これは`path_find status`コマンドに対するレスポンスです。 | | `status` | ブール値 | 値が`true`の場合、これは`path_find status`コマンドに対するレスポンスです。 |
未処理のPathfindingリクエストがない場合はエラーが返されます。 未処理のPathfindingリクエストがない場合はエラーが返されます。

View File

@@ -85,15 +85,16 @@ rippled ripple_path_find '{"source_account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
リクエストには以下のパラメーターが含まれます。 リクエストには以下のパラメーターが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 必須? | 説明 |
|:----------------------|:---------------------------|:------------------------| |:----------------------|:-------------------------|:-------|:-----------------|
| `source_account` | 文字列 | トランザクションで資金を送金するアカウントの一意のアドレス。 | | `source_account` | 文字列 - [アドレス][] | はい | トランザクションで資金を送金するアカウントのアドレス。 |
| `destination_account` | 文字列 | トランザクションで資金を受領するアカウントの一意のアドレス。 | | `destination_account` | 文字列 - [アドレス][] | はい | トランザクションで資金を受領するアカウントのアドレス。 |
| `destination_amount` | 文字列またはオブジェクト | 送金先アカウントがトランザクションで受領する[通貨額][]。**特殊なケース:** {% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %}`value`フィールドには`"-1"`XRPの場合または-1XRP以外の通貨の場合を指定できます。これにより、最大限の額を送金できるパスがリクエストされます。ただし`send_max`が指定されている場合は、指定されている額を上回る額が支払われることはありません。 | | `destination_amount` | [通貨額][] | はい | 送金先アカウントがトランザクションで受領する[通貨額][]。**特殊なケース:** `value`フィールドには`"-1"`XRPの場合または-1XRP以外の通貨の場合を指定できます。これにより、最大限の額を送金できるパスがリクエストされます。ただし`send_max`が指定されている場合は、指定されている額を上回る額が支払われることはありません。 |
| `send_max` | 文字列またはオブジェクト | _省略可_ トランザクションで使用する[通貨額][]。`source_currencies`と同時に使用することはできません。{% badge href="https://github.com/XRPLF/rippled/releases/tag/0.30.0" %}新規: rippled 0.30.0{% /badge %} | | `domain` | 文字列 - [ハッシュ][] | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です) |
| `source_currencies` | 配列 | _省略可_ 送信元アカウントが使用する通貨の配列。この配列の各エントリは、必須の`currency`フィールドとオプションの`issuer`フィールドを有するJSONオブジェクトです[通貨額][]の指定方法と同様)。指定できる送金元通貨は**18**種類以下です。デフォルトでは、あらゆる送金元通貨を使用し、最大で**88**の異なる通貨/イシュアーペアに使用できます。 | | `ledger_hash` | 文字列 - [ハッシュ][] | いいえ | 使用するレジャーバージョンの20バイトの16進文字列。[レジャーの指定][]をご覧ください) |
| `ledger_hash` | 文字列 | _省略可_ 使用するレジャーバージョンの20バイトの16進文字列。([レジャーの指定][]をご覧ください) | | `ledger_index` | [レジャーインデックス][] | いいえ | 使用するレジャーのシーケンス番号、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください) |
| `ledger_index` | 文字列または符号なし整数 | _省略可_ 使用するレジャーのシーケンス番号、またはレジャーを自動的に選択するためのショートカット文字列。([レジャーの指定][]をご覧ください) | | `send_max` | [通貨額][] | いいえ | トランザクションで使用する[通貨額][]。`source_currencies`と同時に使用することはできません。 |
| `source_currencies` | 配列 | いいえ | 送信元アカウントが使用する通貨の配列。この配列の各エントリは、必須の`currency`フィールドとオプションの`issuer`フィールドを有するJSONオブジェクトです[通貨額][]の指定方法と同様)。指定できる送金元通貨は**18**種類以下です。デフォルトでは、あらゆる送金元通貨を使用し、最大で**88**の異なる通貨/イシュアーペアに使用できます。 |
## レスポンスのフォーマット ## レスポンスのフォーマット
@@ -323,7 +324,7 @@ rippled ripple_path_find '{"source_account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
このレスポンスは[標準フォーマット][]に従っており、正常に完了した場合は結果に次のフィールドが含まれます。 このレスポンスは[標準フォーマット][]に従っており、正常に完了した場合は結果に次のフィールドが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:-------------------------|:-------|:-----------------------------------------| |:-------------------------|:-------|:-----------------------------------------|
| `alternatives` | 配列 | 使用可能なパスを持つオブジェクトの配列。以下に説明します。空の場合、送金元アカウントと送金先アカウントを結ぶパスがありません。 | | `alternatives` | 配列 | 使用可能なパスを持つオブジェクトの配列。以下に説明します。空の場合、送金元アカウントと送金先アカウントを結ぶパスがありません。 |
| `destination_account` | 文字列 | 支払トランザクションを受信するアカウントの一意のアドレス。 | | `destination_account` | 文字列 | 支払トランザクションを受信するアカウントの一意のアドレス。 |
@@ -331,7 +332,7 @@ rippled ripple_path_find '{"source_account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
`alternatives`配列の各要素は、1つの送金元通貨開始アカウントが保有から送金先アカウントへのパスと通貨を表すオブジェクトです。このオブジェクトのフィールドを次に示します。 `alternatives`配列の各要素は、1つの送金元通貨開始アカウントが保有から送金先アカウントへのパスと通貨を表すオブジェクトです。このオブジェクトのフィールドを次に示します。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:-----------------|:-----------------|:---------------------------------------| |:-----------------|:-----------------|:---------------------------------------|
| `paths_computed` | 配列 | (省略可)[ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を定義するオブジェクトの配列。 | | `paths_computed` | 配列 | (省略可)[ペイメントパス](../../../../concepts/tokens/fungible-tokens/paths.md)を定義するオブジェクトの配列。 |
| `source_amount` | 文字列またはオブジェクト | 送金先が希望額を受領できるよう、送金元がこのパスで送金する必要のある[通貨額][]。 | | `source_amount` | 文字列またはオブジェクト | 送金先が希望額を受領できるよう、送金元がこのパスで送金する必要のある[通貨額][]。 |

View File

@@ -10,7 +10,7 @@ labels:
- スマートコントラクト - スマートコントラクト
--- ---
# subscribe # subscribe
[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/ripple/rpc/handlers/Subscribe.cpp "Source") [[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/rpc/handlers/Subscribe.cpp "Source")
`subscribe`メソッドは、特定のイベントが発生した場合に、定期的に通知するようサーバにリクエストします。 `subscribe`メソッドは、特定のイベントが発生した場合に、定期的に通知するようサーバにリクエストします。
@@ -66,42 +66,47 @@ labels:
リクエストには以下のパラメーターが含まれます。 リクエストには以下のパラメーターが含まれます。
| `Field` | 型 | 説明 | | フィールド | 型 | 必須? | 説明 |
| :------------------ | :----- | ---- | |:--------------------|:-------|:-------|:-----|
| `streams` | 配列 | _省略可_ 以下説明するサブスクライブする汎用ストリームの文字列名の配列。 | | `streams` | 配列 | いいえ | 以下説明するストリームにサブスクライブします。配列の各要素は、ストリームの文字列名でなければなりません。 |
| `accounts` | 配列 | _省略可_ 検証済みトランザクションを監視するアカウントの一意のアドレスを持つ配列。これらのアドレスはXRP Ledgerの[base58][]フォーマットで記述されている必要があります。サーバは、1つ以上のアカウントに影響するすべてのトランザクションについて通知を送信します。 | | `accounts` | 配列 | いいえ | 検証済みトランザクションを監視するアカウントの一意の[アドレス][]を持つ配列。サーバは、少なくともこれらのアカウントのいずれかに影響を与えるトランザクションが発生するたびに、`transaction`タイプのメッセージを送信します。 |
| `accounts_proposed` | 配列 | _省略可_ `accounts`と同様ですが、まだファイナライズされていないトランザクションを含みます。 | | `accounts_proposed` | 配列 | いいえ | `accounts`と同様ですが、まだファイナライズされていないトランザクションを含みます。 |
| `books` | 配列 | _省略可_ 以下に説明するとおり、更新監視のために[オーダーブック](http://www.investopedia.com/terms/o/order-book.asp)を定義するオブジェクトの配列。 | | `books` | 配列 | いいえ | 更新監視するオーダーブック。配列の各要素は、以下で定義される[book object](#book-objects)でなければなりません。サーバは、トランザクションがこのアカウントに影響を与えるたびに、`transaction`タイプのメッセージを送信します。 |
| `url` | 文字列 | Websocketでは省略可、それ以外では必須サーバが各イベントのJSON-RPCコールバックを送信するURL。*管理者専用。* | | `url` | 文字列 | いいえ | Websocketでは省略可、それ以外では必須サーバが各イベントのJSON-RPCコールバックを送信するURL。*管理者専用。* |
| `url_username` | 文字列 | _省略可_ コールバックURLで基本認証を行うためのユーザ名。 | | `url_username` | 文字列 | いいえ | コールバックURLで基本認証を行うためのユーザ名。 |
| `url_password` | 文字列 | _省略可_ コールバックURLで基本認証を行うためのパスワード。 | | `url_password` | 文字列 | いいえ | コールバックURLで基本認証を行うためのパスワード。 |
以下のパラメータは廃止予定で、今後予告なしに削除される可能性があります。`user``password``rt_accounts` 以下のパラメータは廃止予定で、今後予告なしに削除される可能性があります。`user``password``rt_accounts`
`streams`パラメータは、以下のデフォルトの情報ストリームへのアクセスを可能にします。 `streams`パラメータは、以下のデフォルトの情報ストリームへのアクセスを可能にします。
- `book_changes` - コンセンサスプロセスが新しい有効なレジャーを作成するたびに、オーダーブックの変更をメッセージで送信します。 | ストリーム名 | メッセージタイプ | 説明 |
- `consensus` - サーバがコンセンサスサイクルのフェーズを変更するたびにメッセージを送信します。 |:------------------------|:---------------------|:------------|
- `ledger` - コンセンサスプロセス新しい検証済みレジャー宣言されるたびにメッセージ送信します。 | `book_changes` | `bookChanges` | コンセンサスプロセス新しい検証済みレジャー宣言るたびに、オーダーブックの変更をメッセージ送信します。 |
- `manifests` - バリデータのephemeral署名鍵の更新を受け取るたびにメッセージを送信します。 | `consensus` | `consensusPhase` | サーバがコンセンサスサイクルのフェーズを変更するたびにメッセージを送信します。 |
- `peer_status` - **(管理者専用)** 接続している`rippled`のピアサーバに関する情報(特にコンセンサスプロセスに関する情報)。 | `ledger` | `ledgerClosed` | コンセンサスプロセスで新しい検証済みレジャーが宣言されるたびにメッセージを送信します。 |
- `transactions` - 閉鎖済みレジャーにトランザクションが追加されるたびにメッセージを送信します。 | `manifests` | `manifestReceived` | バリデータのephemeral署名鍵の更新を受け取るたびにメッセージを送信します。 |
- `transactions_proposed` - 閉鎖済みレジャーにトランザクションが追加される場合や、検証済みレジャーにまだ追加されておらず、今後も追加される見込みのない一部のトランザクションが検証済みレジャーに追加される場合に、メッセージを送信します。提案されたすべてのトランザクションが検証前に表示されるわけではありません。 | `peer_status` | `peerStatusChange` | **(管理者専用)** 接続している`rippled`のピアサーバに関する情報(特にコンセンサスプロセスに関する情報)。 |
{% admonition type="info" name="注記" %}[成功しなかったトランザクション](../../../protocol/transactions/transaction-results/index.md) 成功しなかったトランザクションも、スパム対策取引手数料を取るため、検証済みレジャーに含まれます。{% /admonition %} | `transactions` | `transaction` | 閉鎖済みレジャーにトランザクションが追加されるたびにメッセージを送信します。 |
- `server` - `rippled`サーバのステータス(ネットワーク接続など)が変更されるたびにメッセージを送信します。 | `transactions_proposed` | `transaction` | 閉鎖済みレジャーにトランザクションが追加される場合や、検証済みレジャーにまだ追加されておらず、今後も追加される見込みのない一部のトランザクションが検証済みレジャーに追加される場合に、メッセージを送信します。提案されたすべてのトランザクションが検証前に表示されるわけではありません。 {% admonition type="info" name="注記" %}[成功しなかったトランザクション](../../../protocol/transactions/transaction-results/index.md) 成功しなかったトランザクションも、スパム対策取引手数料を取るため、検証済みレジャーに含まれます。{% /admonition %} |
- `validations` - サーバがバリデータを信頼しているか否かにかかわらず、サーバが検証メッセージを受信するたびに、メッセージを送信します。(個々の`rippled`は、サーバが少なくとも定数の信頼できるバリデータから検証メッセージを信した時点で、レジャーが検証済みであると宣言します。 | `server` | `serverStatus` | `rippled`サーバのステータス(ネットワーク接続など)が変更されるたびにメッセージを信します。 |
| `validations` | `validationReceived` | サーバがバリデータを信頼しているか否かにかかわらず、サーバが検証メッセージを受信するたびに、メッセージを送信します。(個々の`rippled`は、サーバが少なくとも定数の信頼できるバリデータから検証メッセージを受信した時点で、レジャーが検証済みであると宣言します。) |
{% admonition type="info" name="注記" %}以下のストリームは Clioおよび[レポートモード][]の`rippled`サーバからは利用できません: `server``peer_status``consensus`。これらのストリームを要求すると、どちらも`reportingUnsupported`エラーを返します。 {% badge href="https://github.com/XRPLF/rippled/releases/tag/1.8.1" %}更新: rippled 1.8.1{% /badge %} {% badge href="https://github.com/XRPLF/clio/releases/tag/2.0.0" %}新規: Clio v2.0{% /badge %}{% /admonition %} {% admonition type="info" name="注記" %}以下のストリームは Clioおよび[レポートモード][]の`rippled`サーバからは利用できません: `server``peer_status``consensus`。これらのストリームを要求すると、どちらも`reportingUnsupported`エラーを返します。 {% badge href="https://github.com/XRPLF/rippled/releases/tag/1.8.1" %}更新: rippled 1.8.1{% /badge %} {% badge href="https://github.com/XRPLF/clio/releases/tag/2.0.0" %}新規: Clio v2.0{% /badge %}{% /admonition %}
### Bookオブジェクト
`books`配列が指定されている場合、この配列の各要素は、以下のフィールドを持つオブジェクトです。 `books`配列が指定されている場合、この配列の各要素は、以下のフィールドを持つオブジェクトです。
| `Field` | 型 | 説明 | | フィールド | 型 | 必須? | 説明 |
| :----------- | :----------- | ---- | | :----------- | :-------------------- | :----- | ---- |
| `taker_gets` | オブジェクト | オファーを受諾するアカウントが受け取る通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 | | `taker_gets` | オブジェクト | はい | オファーを受諾するアカウントが受け取る通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 |
| `taker_pays` | オブジェクト | オファーを受諾するアカウントが支払う通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 | | `taker_pays` | オブジェクト | はい | オファーを受諾するアカウントが支払う通貨を[金額なしの通貨オブジェクト](../../../protocol/data-types/currency-formats.md#金額なしでの通貨の指定)として指定します。 |
| `taker` | 文字列 | オファーを表示するパースペクティブとして使用する一意のアカウントアドレスXRP Ledgerの[base58][]フォーマット)。(これはオファーの資金提供ステータスと手数料に影響します。) | | `both` | ブール値 | いいえ | `true`の場合は、オーダーブックの両サイドを返します。デフォルトは`false` |
| `snapshot` | ブール値 | (省略可)`true`の場合は、更新の送信前にサブスクライブした時点でオーダーブックの現在の状態を一度返します。デフォルトは`false` | | `domain` | 文字列 - [ハッシュ][] | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です) |
| `both` | ブール値 | (省略可)`true`の場合は、オーダーブックの両サイドを返します。デフォルトは`false` | | `snapshot` | ブール値 | いいえ | `true`の場合は、更新の送信前にサブスクライブした時点でオーダーブックの現在の状態を一度返します。デフォルトは`false` |
| `taker` | 文字列 | いいえ | オファーを表示するパースペクティブとして使用する一意のアカウントアドレスXRP Ledgerの[base58][]フォーマット)。(これはオファーの資金提供ステータスと手数料に影響します。) |
## レスポンスのフォーマット ## レスポンスのフォーマット
@@ -167,7 +172,7 @@ labels:
レジャーストリームメッセージのフィールドは次のとおりです。 レジャーストリームメッセージのフィールドは次のとおりです。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
| :------------------ | :------------------------------ | ---- | | :------------------ | :------------------------------ | ---- |
| `type` | 文字列 | `ledgerClosed`は、このメッセージがレジャーストリームからのものであることを示します。 | | `type` | 文字列 | `ledgerClosed`は、このメッセージがレジャーストリームからのものであることを示します。 |
| `fee_base` | 数値 | このレジャーバージョン時点の[Referenceトランザクションコスト](../../../../concepts/transactions/transaction-cost.md#referenceトランザクションコスト)[XRPのdrop数][])。このレジャーバージョンに[SetFee疑似トランザクション](../../../protocol/transactions/pseudo-transaction-types/setfee.md)が含まれている場合は、次のレジャーバージョンから新しいトランザクションコストが適用されます。 | | `fee_base` | 数値 | このレジャーバージョン時点の[Referenceトランザクションコスト](../../../../concepts/transactions/transaction-cost.md#referenceトランザクションコスト)[XRPのdrop数][])。このレジャーバージョンに[SetFee疑似トランザクション](../../../protocol/transactions/pseudo-transaction-types/setfee.md)が含まれている場合は、次のレジャーバージョンから新しいトランザクションコストが適用されます。 |
@@ -212,7 +217,7 @@ labels:
検証ストリームメッセージのフィールドは次のとおりです。 検証ストリームメッセージのフィールドは次のとおりです。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
| :---------------------- | :------------ | ---- | | :---------------------- | :------------ | ---- |
| `type` | 文字列 | 値`validationReceived`は、このメッセージが検証ストリームからであることを示します。 | | `type` | 文字列 | 値`validationReceived`は、このメッセージが検証ストリームからであることを示します。 |
| `amendments` | 文字列の配列 | (省略される場合があります)このサーバがプロトコルへの追加を求める[Amendment](../../../../concepts/networks-and-servers/amendments.md)。 | | `amendments` | 文字列の配列 | (省略される場合があります)このサーバがプロトコルへの追加を求める[Amendment](../../../../concepts/networks-and-servers/amendments.md)。 |
@@ -333,7 +338,7 @@ labels:
{% tab label="API v2" %} {% tab label="API v2" %}
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
|:------------------------|:--------------------------|:-----| |:------------------------|:--------------------------|:-----|
| `close_time_iso` | 文字列 | レジャーの終了時刻をISO 8601の時刻形式で表します。 | | `close_time_iso` | 文字列 | レジャーの終了時刻をISO 8601の時刻形式で表します。 |
| `type` | 文字列 | `transaction`は、複数の可能なストリームからのトランザクションの通知であることを示します。 | | `type` | 文字列 | `transaction`は、複数の可能なストリームからのトランザクションの通知であることを示します。 |
@@ -352,7 +357,7 @@ labels:
{% tab label="API v1" %} {% tab label="API v1" %}
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
| :---------------------- | :------------------------------ | ---- | | :---------------------- | :------------------------------ | ---- |
| `type` | 文字列 | `transaction`は、トランザクションの通知であることを示します。この通知はさまざまなストリームから送信される可能性があります。 | | `type` | 文字列 | `transaction`は、トランザクションの通知であることを示します。この通知はさまざまなストリームから送信される可能性があります。 |
| `engine_result` | 文字列 | 文字列の[トランザクション結果コード](../../../protocol/transactions/transaction-results/index.md) | | `engine_result` | 文字列 | 文字列の[トランザクション結果コード](../../../protocol/transactions/transaction-results/index.md) |
@@ -389,7 +394,7 @@ labels:
ピアステータスストリームメッセージは、`rippled`ピアサーバのステータスが変化したイベントを表します。これらのメッセージは、次のフィールドを持つJSONオブジェクトです。 ピアステータスストリームメッセージは、`rippled`ピアサーバのステータスが変化したイベントを表します。これらのメッセージは、次のフィールドを持つJSONオブジェクトです。
| `Field` | 値 | 説明 | | フィールド | 値 | 説明 |
| :----------------- | :----- | ---- | | :----------------- | :----- | ---- |
| `type` | 文字列 | `peerStatusChange`は、ピアステータスストリームからのメッセージであることを示します。 | | `type` | 文字列 | `peerStatusChange`は、ピアステータスストリームからのメッセージであることを示します。 |
| `action` | 文字列 | このメッセージが送信される原因となったイベントのタイプ。有効な値については、[ピアステータスイベント](#ピアステータスイベント)をご覧ください。 | | `action` | 文字列 | このメッセージが送信される原因となったイベントのタイプ。有効な値については、[ピアステータスイベント](#ピアステータスイベント)をご覧ください。 |
@@ -561,7 +566,7 @@ labels:
オーダーブックストリームメッセージの形式は、[トランザクションストリームメッセージ](#トランザクションストリーム)と同様ですが、`OfferCreate`トランザクションに以下のフィールドも含まれている点が異なります。 オーダーブックストリームメッセージの形式は、[トランザクションストリームメッセージ](#トランザクションストリーム)と同様ですが、`OfferCreate`トランザクションに以下のフィールドも含まれている点が異なります。
| `Field` | 値 | 説明 | | フィールド | 値 | 説明 |
| :------------------------ | :----- | ---- | | :------------------------ | :----- | ---- |
| `transaction.owner_funds` | 文字列 | このOfferCreateトランザクションを送信する`Account`が、このトランザクション実行後に有する`TakerGets`通貨の金額。この通貨額が[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。<br>[API v2][]では`tx_json.owner_funds`に変更されました。 | | `transaction.owner_funds` | 文字列 | このOfferCreateトランザクションを送信する`Account`が、このトランザクション実行後に有する`TakerGets`通貨の金額。この通貨額が[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。<br>[API v2][]では`tx_json.owner_funds`に変更されました。 |
@@ -695,7 +700,7 @@ labels:
[Book Changes]ストリームメッセージのフィールドは以下のとおりです: [Book Changes]ストリームメッセージのフィールドは以下のとおりです:
| Field | 値 | 説明 | | フィールド | 値 | 説明 |
|:---------------|:-------------------------|:-----| |:---------------|:-------------------------|:-----|
| `type` | 文字列 | 値`bookChanges`は、これがBook Changesストリームからのものであることを示します。 | | `type` | 文字列 | 値`bookChanges`は、これがBook Changesストリームからのものであることを示します。 |
| `ledger_index` | [レジャーインデックス][] | これらの変更を含むレジャーのレジャーインデックス。 | | `ledger_index` | [レジャーインデックス][] | これらの変更を含むレジャーのレジャーインデックス。 |
@@ -717,7 +722,7 @@ labels:
コンセンサスストリームメッセージのフィールドは次のとおりです。 コンセンサスストリームメッセージのフィールドは次のとおりです。
| `Field` | 型 | 説明 | | フィールド | 型 | 説明 |
| :---------- | :----- | ---- | | :---------- | :----- | ---- |
| `type` | 文字列 | `consensusPhase`は、このメッセージがコンセンサスストリームからのものであることを示します。 | | `type` | 文字列 | `consensusPhase`は、このメッセージがコンセンサスストリームからのものであることを示します。 |
| `consensus` | 文字列 | サーバで実行されている新しいコンセンサスフェーズ。値には、`open``establish``accepted`などがあります。 | | `consensus` | 文字列 | サーバで実行されている新しいコンセンサスフェーズ。値には、`open``establish``accepted`などがあります。 |

View File

@@ -73,7 +73,7 @@ XRPの金額は負になることはありません。
} }
``` ```
#### 金額なしでの通貨の指定 ### 金額なしでの通貨の指定
場合によっては、[分散型取引所](../../../concepts/tokens/decentralized-exchange/index.md)でオーダーブックを指定するときなど、特定の金額なしで資産(XRPやトークン)を定義する必要があります。 場合によっては、[分散型取引所](../../../concepts/tokens/decentralized-exchange/index.md)でオーダーブックを指定するときなど、特定の金額なしで資産(XRPやトークン)を定義する必要があります。

View File

@@ -6,7 +6,7 @@ labels:
- 分散型取引所 - 分散型取引所
--- ---
# DirectoryNode # DirectoryNode
[[ソース]](https://github.com/XRPLF/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L44 "Source") [[ソース]](https://github.com/XRPLF/rippled/blob/7e24adbdd0b61fb50967c4c6d4b27cc6d81b33f3/include/xrpl/protocol/detail/ledger_entries.macro#L177-L192 "Source")
`DirectoryNode`オブジェクトタイプは、レジャーの状態ツリー内の他オブジェクトへのリンクのリストを提供します。概念上の1つの _ディレクトリ_ は、1つ以上の各DirectoryNodeオブジェクトが含まれる二重リンクリストの形式になっています。各DirectoryNodeオブジェクトには、他オブジェクトの[ID](../common-fields.md)が最大32個まで含まれています。1番目のオブジェクトはディレクトリのルートと呼ばれ、ルートオブジェクト以外のオブジェクトはすべて必要に応じて自由に追加または削除できます。 `DirectoryNode`オブジェクトタイプは、レジャーの状態ツリー内の他オブジェクトへのリンクのリストを提供します。概念上の1つの _ディレクトリ_ は、1つ以上の各DirectoryNodeオブジェクトが含まれる二重リンクリストの形式になっています。各DirectoryNodeオブジェクトには、他オブジェクトの[ID](../common-fields.md)が最大32個まで含まれています。1番目のオブジェクトはディレクトリのルートと呼ばれ、ルートオブジェクト以外のオブジェクトはすべて必要に応じて自由に追加または削除できます。
@@ -95,6 +95,7 @@ labels:
| 名前 | JSONの型 | [内部の型][] | 必須? | 説明 | | 名前 | JSONの型 | [内部の型][] | 必須? | 説明 |
|---------------------|-----------|--------------|:-------|-------------| |---------------------|-----------|--------------|:-------|-------------|
| `DomainID` | 文字列 | Hash256 | いいえ | (オファーディレクトリのみ) 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) |
| `ExchangeRate` | 数値 | UInt64 | いいえ | (オファーディレクトリのみ)**廃止予定**。使用しないでください。 | | `ExchangeRate` | 数値 | UInt64 | いいえ | (オファーディレクトリのみ)**廃止予定**。使用しないでください。 |
| `Flags` | 数値 | UInt32 | はい | このディレクトリに対して有効になっているブール値フラグのビットマップ。現在、プロトコルではDirectoryNodeオブジェクトのフラグは定義されていません。 | | `Flags` | 数値 | UInt32 | はい | このディレクトリに対して有効になっているブール値フラグのビットマップ。現在、プロトコルではDirectoryNodeオブジェクトのフラグは定義されていません。 |
| `Indexes` | 配列 | Vector256 | はい | このディレクトリの内容: 他のオブジェクトのIDの配列。 | | `Indexes` | 配列 | Vector256 | はい | このディレクトリの内容: 他のオブジェクトのIDの配列。 |
@@ -135,6 +136,7 @@ DirectoryNodeのIDを作成するときには、DirectoryNodeが以下のどの
* 所有者ディレクトリまたはNFTオファーディレクトリの1番目のページルートとも呼ばれます * 所有者ディレクトリまたはNFTオファーディレクトリの1番目のページルートとも呼ばれます
* オファーディレクトリの1番目のページ * オファーディレクトリの1番目のページ
* オファーディレクトリの最初のページ。オープンDEXと認可型DEX用のバージョンが含まれます。 _([PermissionedDEX amendment][]が必要です。 {% not-enabled /%})_
* いずれかのディレクトリの以降のページ * いずれかのディレクトリの以降のページ
**所有者ディレクトリまたはNFTオファーディレクトリの1番目のページ**のIDは、以下の値がこの順序で連結されている[SHA-512Half][]です。 **所有者ディレクトリまたはNFTオファーディレクトリの1番目のページ**のIDは、以下の値がこの順序で連結されている[SHA-512Half][]です。
@@ -149,6 +151,7 @@ DirectoryNodeのIDを作成するときには、DirectoryNodeが以下のどの
* `TakerGetsCurrency`の160ビットの通貨コード * `TakerGetsCurrency`の160ビットの通貨コード
* `TakerPaysIssuer`のAccountID * `TakerPaysIssuer`のAccountID
* `TakerGetsIssuer`のAccountID * `TakerGetsIssuer`のAccountID
* このオーダーブックが属する許可型DEXの許可型ドメインの`DomainID`。許可型DEXのオーダーブックの場合。オープンDEXのオーダーブックの場合は省略。
オファーディレクトリのIDの下位64ビットは、そのディレクトリ内のオファーのTakerPaysの額をTakerGetsの額で割った結果を、XRP Ledgerの内部金額フォーマットの64ビット数値で表したものです。 オファーディレクトリのIDの下位64ビットは、そのディレクトリ内のオファーのTakerPaysの額をTakerGetsの額で割った結果を、XRP Ledgerの内部金額フォーマットの64ビット数値で表したものです。

View File

@@ -7,9 +7,9 @@ labels:
- 分散型取引所 - 分散型取引所
--- ---
# Offer # Offer
[[ソース]](https://github.com/XRPLF/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L57 "Source") [[ソース]](https://github.com/XRPLF/rippled/blob/7e24adbdd0b61fb50967c4c6d4b27cc6d81b33f3/include/xrpl/protocol/detail/ledger_entries.macro#L242-L255 "ソース")
台帳の`Offer`エントリは、XRP Ledgerの[分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)で通貨を交換する[オファー](../../../../concepts/tokens/decentralized-exchange/offers.md)を表しています。(金融ではより伝統的に _オーダー_ として知られています)。[OfferCreateトランザクション][]は台帳にある他のOfferを全額約定できない場合、台帳に`Offer`エントリを作成します。 `Offer`レジャーエントリは、XRP Ledgerの[分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)で通貨を交換する[オファー](../../../../concepts/tokens/decentralized-exchange/offers.md)を表しています。(金融ではより伝統的に _オーダー_ として知られています)。[OfferCreateトランザクション][]は他のOfferを全額約定できない場合、Offerエントリを作成します。
オファーがネットワーク上の他の活動によって資金不足になることはありますが、元帳には残ります。トランザクションを処理する際、ネットワークはトランザクションが見つけた資金不足のオファーを自動的に削除します。( _トランザクションのみ_ が台帳の状態を変更できるため、削除が行われないと資金不足のオファーが残ってしまいます。) オファーがネットワーク上の他の活動によって資金不足になることはありますが、元帳には残ります。トランザクションを処理する際、ネットワークはトランザクションが見つけた資金不足のオファーを自動的に削除します。( _トランザクションのみ_ が台帳の状態を変更できるため、削除が行われないと資金不足のオファーが残ってしまいます。)
@@ -40,29 +40,32 @@ labels:
[共通フィールド][]に加えて、{% $frontmatter.seo.title %}エントリは以下のフィールドを使用します。 [共通フィールド][]に加えて、{% $frontmatter.seo.title %}エントリは以下のフィールドを使用します。
| 名前 | JSONの型 | [内部の型][] | 必須? | 説明 | | 名前 | JSONの型 | [内部の型][] | 必須? | 説明 |
|-------------------|-----------|-----------|------|-------| |---------------------|-----------------------|--------------|-------|-------|
| `Account` | 文字列 | AccountID | はい | このオファーを所有するアカウントのアドレス。 | | `Account` | 文字列 | AccountID | はい | このオファーを所有するアカウントのアドレス。 |
| `BookDirectory` | 文字列 | UInt256 | はい | このオファーにリンクしている[オファーディレクトリー](directorynode.md)のID。 | | `AdditionalBooks` | 配列 | Array | いいえ| 追加のオファーディレクトリーのリスト。このフィールドは、このオファーが[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)でハイブリッドオファーの場合にのみ存在します。配列には常に1つのエントリが含まれます。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) |
| `BookNode` | 文字列 | UInt64 | はい | Offerディレクトリが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。 | | `BookDirectory` | 文字列 - [ハッシュ][] | UInt256 | はい | このオファーにリンクしている[オファーディレクトリー](directorynode.md)のID。 |
| `Expiration` | 数値 | UInt32 | いいえ | (省略可)このオファーが資金不足とみなされる時刻。詳細は、[時間の指定][]をご覧ください。 | | `BookNode` | 文字列 | UInt64 | はい | Offerディレクトリが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。 |
| `Flags` | 数値 | UInt32 | はい | このオファーに対して有効になっているブール値フラグのビットマップ。 | | `DomainID` | 文字列 - [ハッシュ][] | Hash256 | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) |
| `LedgerEntryType` | 文字列 | UInt16 | はい | 値が`0x006F`(文字列`Offer`にマッピング)の場合は、このオブジェクトが通貨取引オーダーを記述することを示す。 | | `Expiration` | 数値 | UInt32 | いいえ | (省略可)このオファーが資金不足とみなされる時刻。詳細は、[時間の指定][]をご覧ください。 |
| `OwnerNode` | 文字列 | UInt64 | はい | 所有者ディレクトリーが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。**注記:** このオファーには、オファーを含む所有者ディレクトリーへの直接リンクは含まれていません。これは、その値を`Account`から取得できるためです。 | | `Flags` | 数値 | UInt32 | はい | このオファーに対して有効になっているブール値フラグのビットマップ。 |
| `PreviousTxnID` | 文字列 | UInt256 | はい | 最後にこのオブジェクトを変更したトランザクションの識別用ハッシュ。 | | `LedgerEntryType` | 文字列 | UInt16 | はい | 値が`0x006F`(文字列`Offer`にマッピング)の場合は、このオブジェクトが通貨取引オーダーを記述することを示す。 |
| `Sequence` | 数値 | UInt32 | はい | `Offer`オブジェクトを作成した[OfferCreate][]トランザクションの`Sequence`値。`Account`とこのフィールドの組み合わせによってこのオファーが識別されます。 | | `OwnerNode` | 文字列 | UInt64 | はい | 所有者ディレクトリーが複数ページで構成されている場合に、このオブジェクトにリンクしているページを示すヒント。**注記:** このオファーには、オファーを含む所有者ディレクトリーへの直接リンクは含まれていません。これは、その値を`Account`から取得できるためです。 |
| `PreviousTxnID` | 文字列 - [ハッシュ][] | UInt256 | はい | 最後にこのオブジェクトを変更したトランザクションの識別用ハッシュ。 |
| `Sequence` | 数値 | UInt32 | はい | `Offer`オブジェクトを作成した[OfferCreate][]トランザクションの`Sequence`値。`Account`とこのフィールドの組み合わせによってこのオファーが識別されます。 |
| `PreviousTxnLgrSeq` | 数値 | UInt32 | はい | 最後にこのオブジェクトを変更したトランザクションが記録された[レジャーインデックス][]。 | | `PreviousTxnLgrSeq` | 数値 | UInt32 | はい | 最後にこのオブジェクトを変更したトランザクションが記録された[レジャーインデックス][]。 |
| `TakerPays` | 文字列またはオブジェクト | Amount | はい | オファー作成者がリクエストする残額と通貨の種類。 | | `TakerPays` | [通貨額][] | Amount | はい | オファー作成者がリクエストする残額と通貨の種類。 |
| `TakerGets` | 文字列またはオブジェクト | Amount | はい | オファー作成者が提供する残額と通貨の種類。 | | `TakerGets` | [通貨額][] | Amount | はい | オファー作成者が提供する残額と通貨の種類。 |
## Offerのフラグ ## Offerのフラグ
`Offer`エントリは以下のフラグを`Flags`フィールドに指定することができます。 `Offer`エントリは以下のフラグを`Flags`フィールドに指定することができます。
| フラグ名 | 16進数値 | 10進数値 | 対応する[OfferCreateフラグ](../../transactions/types/offercreate.md#offercreateフラグ) | 説明 | | フラグ名 | 16進数値 | 10進数値 | 対応する[OfferCreateフラグ](../../transactions/types/offercreate.md#offercreateフラグ) | 説明 |
|-----------|-----------|---------------|-------------|------------------------| |--------------|--------------|----------|-------------|------------------------|
| `lsfPassive` | `0x00010000` | 65536 | `tfPassive` | オブジェクトはパッシブオファーとして発注されています。レジャー内のオブジェクトには影響しません。 | | `lsfPassive` | `0x00010000` | 65536 | `tfPassive` | オブジェクトはパッシブオファーとして発注されています。レジャー内のオブジェクトには影響しません。 |
| `lsfSell` | `0x00020000` | 131072 | `tfSell` | オブジェクトは売却オファーとして発注されています。これは台帳にあるオブジェクトには何の影響もありません (`tfSell`は指定したレートよりも良いレートが存在する場合にのみ意味を持ち、台帳にこのフラグを持ったオブジェクトが入ることはありません。)。 | | `lsfSell` | `0x00020000` | 131072 | `tfSell` | オブジェクトは売却オファーとして発注されています。これは台帳にあるオブジェクトには何の影響もありません (`tfSell`は指定したレートよりも良いレートが存在する場合にのみ意味を持ち、台帳にこのフラグを持ったオブジェクトが入ることはありません。)。 |
| `lsfHybrid` | `0x00040000` | 262144 | `tfHybrid` | ハイブリッドオファーとして作成されています。これは、[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)と公開DEXの両方にリストされていることを意味します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) |
## {% $frontmatter.seo.title %}の準備金 ## {% $frontmatter.seo.title %}の準備金
@@ -78,6 +81,6 @@ labels:
* オファーを行うアカウントのAccountID * オファーを行うアカウントのAccountID
* オファーを作成した[OfferCreateトランザクション][]のシーケンス番号 * オファーを作成した[OfferCreateトランザクション][]のシーケンス番号
OfferCreateトランザクションが[Ticket](../../../../concepts/accounts/tickets.md)を使用した場合、代わりに`TicketSequence`値を使用します。 OfferCreateトランザクションが[チケット](../../../../concepts/accounts/tickets.md)を使用した場合、代わりに`TicketSequence`値を使用します。
{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -100,4 +100,4 @@ _([PermissionedDomains amendment][]が必要です {% not-enabled /%})_
3. 作成した{% code-page-name /%}トランザクションのシーケンス番号 3. 作成した{% code-page-name /%}トランザクションのシーケンス番号
{% raw-partial file="/docs/_snippets/common-links.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -55,7 +55,7 @@ AMMのLPトークンを使って落札すると、落札に利用したLPトー
{% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%}
| フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 |
|:---------------|:-----------|:- ----------|:----- |:------------| |:---------------|:-----------|:------------|:------|:------------|
| `Asset` | オブジェクト | STIssue | はい | AMMのプールにある資産の一つを定義します。JSONでは、`currency``issuer`フィールドを持つオブジェクトになりますXRPの場合は`issuer`を省略します)。 | | `Asset` | オブジェクト | STIssue | はい | AMMのプールにある資産の一つを定義します。JSONでは、`currency``issuer`フィールドを持つオブジェクトになりますXRPの場合は`issuer`を省略します)。 |
| `Asset2` | オブジェクト | STIssue | はい | AMMのプールにあるもう一つのアセットの定義です。JSONでは、`currency``issuer`フィールドを持つオブジェクトになりますXRPの場合は`issuer`を省略します)。 | | `Asset2` | オブジェクト | STIssue | はい | AMMのプールにあるもう一つのアセットの定義です。JSONでは、`currency``issuer`フィールドを持つオブジェクトになりますXRPの場合は`issuer`を省略します)。 |
| `BidMin` | [通貨額][] | Amount | いいえ | スロットに支払う最小の金額。この値を高く設定すると、他の人から競り落とされにくくなります。省略された場合は、落札に必要な最低額を支払います。 | | `BidMin` | [通貨額][] | Amount | いいえ | スロットに支払う最小の金額。この値を高く設定すると、他の人から競り落とされにくくなります。省略された場合は、落札に必要な最低額を支払います。 |

View File

@@ -0,0 +1,81 @@
---
seo:
description: 自動マーケットメーカープールに発行済みトークンを預け入れた保有者から、トークンを回収する。
labels:
- AMM
- Tokens
---
# AMMClawback
[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/tx/detail/AMMClawback.cpp "ソース")
発行したトークンをAMMプールに預け入れた保有者からトークンを回収します。
Clawbackはデフォルトで無効です。Clawbackを使用するには、[AccountSetトランザクション][]を送信して、**Allow Trust Line Clawback**設定を有効にする必要があります。すでにトークンが発行済みである発行者はClawbackを有効にできません。**Allow Trust Line Clawback**を有効にするには、トラストライン、オファー、エスクロー、ペイメントチャネル、チェック、署名者リストを設定する前に、所有者ディレクトリを完全に空にする必要があります。Clawbackを有効にした後は、元に戻すことはできません。つまり発行者アカウントは、トラストラインの発行済みトークンを回収できる権利を永続的に得ます。
_([AMMClawback amendment][]により追加されました。)_
## {% $frontmatter.seo.title %} JSONの例
```json
{
"TransactionType": "AMMClawback",
"Account": "rPdYxU9dNkbzC5Y2h4jLbVJ3rMRrk7WVRL",
"Holder": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"Asset": {
"currency" : "FOO",
"issuer" : "rPdYxU9dNkbzC5Y2h4jLbVJ3rMRrk7WVRL"
},
"Asset2" : {
"currency" : "BAR",
"issuer" : "rHtptZx1yHf6Yv43s1RWffM3XnEYv3XhRg"
},
"Amount": {
"currency" : "FOO",
"issuer" : "rPdYxU9dNkbzC5Y2h4jLbVJ3rMRrk7WVRL",
"value" : "1000"
}
}
```
{% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%}
| フィールド | JSONの型 | [内部の型][] | 必須? | 説明 |
|:-----------|:----------------------|:-------------|:-------|:------------------|
| `Account` | 文字列 - [アドレス][] | AccountID | はい | 回収する資産の発行者。このトランザクションは、発行者のみが送信できます。 |
| `Asset` | オブジェクト | Issue | はい | AMMプールから回収したい資産を指定します。資産はXRP、トークン、またはMPT[金額なしの指定][]を参照)です。`issuer`フィールドは`Account`と一致していなければなりません。 |
| `Asset2` | オブジェクト | Issue | はい | AMMのプール内のもう一方の資産を指定します。資産はXRP、トークン、またはMPT[金額なしの指定][]を参照)です。 |
| `Amount` | [通貨額][] | Amount | いいえ | AMMアカウントから回収する最大額を指定します。`currency``issuer`サブフィールドは`Asset`サブフィールドと一致していなければなりません。このフィールドが指定されていない場合、または`value`サブフィールドがAMMの保有者の利用可能なトークンを超えている場合、保有者のすべてのトークンが回収されます。 |
| `Holder` | 文字列 - [アドレス][] | AccountID | はい | 回収する資産を保有しているアカウント。 |
## AMMClawbackのフラグ
| フラグ名 | Hex値 | 10進数値 | 説明 |
|-------------------|--------------|----------|-------------|
| `tfClawTwoAssets` | `0x00000001` | 1 | `Asset`の指定額を回収し、AMMプールの資産比率に基づいて`Asset2`の対応する額を回収します。両方の資産は`Account`フィールドの発行者によって発行されなければなりません。このフラグが有効でない場合、発行者は`Asset`の指定された額を回収しますが、`Asset2`の対応する比率は`Holder`に返されます。 |
## エラーのケース
すべてのトランザクションで発生する可能性のあるエラーに加えて、`AMMClawback`トランザクションは以下の[トランザクション結果コード](../transaction-results/index.md)をもたらすことがあります。
| エラーコード | 説明 |
|:-------------------|:------------|
| `tecNO_PERMISSION` | `lsfAllowTrustlineClawback` フラグが有効になっていない状態で AMM からトークンを回収しようとした場合、または AMM で両方の資産を発行していない状態で `tfClawTwoAssets` フラグが有効になっている場合に発生します。また、`Asset` の発行者が `Account` と一致しない場合にも発生します。 |
| `tecAMM_BALANCE` | `Holder`がAMMプールのLPトークンを保有していない場合に発生します。 |
| `temDISABLED` | [AMMClawback amendment][]が有効になっていない場合に発生します。 |
| `temBAD_AMOUNT` | `AMMClawback`トランザクションの`Amount`フィールドが0以下の場合、または`currency``issuer`サブフィールドが`Amount``Asset`の間で一致しない場合に発生します。 |
| `temINVALID_FLAG` | `tfClawTwoAssets`以外のフラグを有効にしようとした場合に発生します。 |
| `temMALFORMED` | `issuer`サブフィールドが`Asset``Account`の間で一致しない場合、`Account``Holder`と同じ場合、または`Asset`がXRPの場合に発生します。 |
| `terNO_AMM` | `Asset``Asset2`で指定されたAMMプールが存在しない場合に発生します。 |
## 関連項目
- [AMMエントリ][]
{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -39,12 +39,12 @@ AMMを表す[AMMエントリ][]と[特殊なAccountRootエントリ](../../ledge
{% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%}
| フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 |
|:-------------|:---- -----|:-----------|:------|:------------| |:-------------|:----------|:-----------|:------|:------------|
| `Amount` | [通貨額][] | Amount | はい | このAMMの最初の資金となる2つの資産のうち、1つ目の資産です。これは正数である必要があります。 | | `Amount` | [通貨額][] | Amount | はい | このAMMの最初の資金となる2つの資産のうち、1つ目の資産です。これは正数である必要があります。 |
| `Amount2` | [通貨額][] | Amount | はい | このAMMの最初の資金となる2つの資産のうち、2つ目の資産です。これは正数である必要があります。 | | `Amount2` | [通貨額][] | Amount | はい | このAMMの最初の資金となる2つの資産のうち、2つ目の資産です。これは正数である必要があります。 |
| `TradingFee` | 数値 | UInt16 | はい | このAMMインスタンスに対する取引に課される手数料を1/100,000単位で指定します値1は0.001%に相当)。最大値は`1000`で、1%の手数料を意味します。最小値は `0`です。 | | `TradingFee` | 数値 | UInt16 | はい | このAMMインスタンスに対する取引に課される手数料を1/100,000単位で指定します値1は0.001%に相当)。最大値は`1000`で、1%の手数料を意味します。最小値は `0`です。 |
`Amount``Amount2`の一方または両方は[トークン](../../../../concepts/tokens/index.md)であり、最大でどちらか一方を[XRP](../../../../introduction/what-is-xrp.md)にすることが可能です。通貨コードと発行者が同じものは使用できません。AMMのLPトークンは、別のAMMの資産の1つとして使用することができます。トークンの発行者は[Default Ripple](../../../../concepts/tokens/fungible-tokens/rippling.md#defaultrippleフラグ)を有効にしていなければなりません。[Clawback Amendment][] が有効になっている場合、それらの発行者はAllow Clawbackフラグを有効にしていてはいけません。AMMのLPトークンは、別のAMMの資産の一つとして使用することはできません。 `Amount``Amount2`の一方または両方は[トークン](../../../../concepts/tokens/index.md)であり、最大でどちらか一方を[XRP](../../../../introduction/what-is-xrp.md)にすることが可能です。通貨コードと発行者が同じものは使用できません。AMMのLPトークンは、別のAMMの資産の1つとして使用することができます。トークンの発行者は[Default Ripple](../../../../concepts/tokens/fungible-tokens/rippling.md#defaultrippleフラグ)を有効にしていなければなりません。AMMのLPトークンは、別のAMMの資産の一つとして使用することはできません。
## 特殊なトランザクションコスト ## 特殊なトランザクションコスト
@@ -54,17 +54,19 @@ AMMを表す[AMMエントリ][]と[特殊なAccountRootエントリ](../../ledge
すべてのトランザクションで発生する可能性のあるエラーに加えて、{% $frontmatter.seo.title %}トランザクションでは、次の[トランザクション結果コード](../transaction-results/index.md)が発生する可能性があります。 すべてのトランザクションで発生する可能性のあるエラーに加えて、{% $frontmatter.seo.title %}トランザクションでは、次の[トランザクション結果コード](../transaction-results/index.md)が発生する可能性があります。
| エラーコード | 説明 | | エラーコード | 説明 |
|:--------------------|:---------------------------------------------| |:--------------------|:---------------------------------------------|
| `temDISABLED` | このネットワークでは、AMM機能 | | `tecAMM_INVALID_TOKENS` | `Amount`または`Amount2`が、このAMMのLPトークンと同じ通貨コードを使用しています。(これが起こることは稀です。) |
| `temINVALID_FLAG` | トランザクションに無効な`Flags`値が指定されています。現在、このトランザクションタイプに定義されたフラグはないので、[グローバルフラグ](../common-fields.md#グローバルフラグ)のみが許可されます。 | | `tecDUPLICATE` | この通貨ペアを扱っているAMMが既に存在しています。 |
| `temBAD_AMM_TOKENS` | `Amount``Amount2`値が正しくありません。例えば、両方とも同じトークンを参照している場合です。 | | `tecFROZEN` | 資産(`Amount`または`Amount2`)の少なくとも1つが現在[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
| `temBAD_FEE` | `TradingFee`の値が不正です。ゼロまたは正の整数でなければならず、1000を超えることはできません。 | | `tecINSUF_RESERVE_LINE` | 送信者は、このトランザクションを処理するための[準備金要件](../../../../concepts/accounts/reserves.md)を満たしていません。おそらく、LPトークンを保持するための新しいトラストラインが必要で、新しいトラストラインの所有者準備金を満たす十分なXRPを持っていないためです。 |
| `terNO_ACCOUNT` | リクエストで参照されたいずれかのアカウントが存在しません。| | `tecNO_AUTH` | 送信者は資産(`Amount`または`Amount2`)のいずれかを保有する権限がありません。 |
| `tecNO_AUTH` | 送信者は資産`Amount`または`Amount2`)のいずれかを保有する権限がありません。 | | `tecNO_LINE` | 送信者は資産(`Amount`または`Amount2`)のうちいずれか1つに対するトラストラインを保有していません。 |
| `tecNO_LINE` | 送信者は資産(`Amount`または`Amount2`のうちいずれか1つに対するトラストラインを保有していません。 | | `tecNO_PERMISSION` | 少なくとも1つの入金資産はAMMで使用できません。 |
| `tecFROZEN` | 資産(`Amount`または`Amount2`の少なくとも1つが現在[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
| `tecUNFUNDED_AMM` | 送信者は`Amount``Amount2`で指定された金額をAMMに入金するための十分な資金を保有していません。 | | `tecUNFUNDED_AMM` | 送信者は`Amount``Amount2`で指定された金額をAMMに入金するための十分な資金を保有していません。 |
| `tecAMM_EXISTS` | この通貨ペアを扱っているAMMが既に存在していま。 | | `terNO_RIPPLE` | 少なくとも1つの資産の発行者が[Default Rippleフラグ](../../../../concepts/tokens/fungible-tokens/rippling.md#defaultrippleフラグ)を有効にしていません。 |
| `temAMM_BAD_TOKENS` | `Amount``Amount2`値が正しくありません。例えば、両方とも同じトークンを参照している場合です。 |
| `temBAD_FEE` | `TradingFee`の値が不正です。ゼロまたは正の整数でなければならず、1000を超えることはできません。 |
| `temDISABLED` | このネットワークでは、AMM機能が無効になっています。 |
{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -137,7 +137,7 @@ AMMDepositトランザクションは、以下のような[`Flags`フィール
| `tecAMM_EMPTY` | 現在、AMM は資産を保有していないため、通常の入金はできません。代わりに、空のAMMの場合の特殊な入金を行う必要があります。 | | `tecAMM_EMPTY` | 現在、AMM は資産を保有していないため、通常の入金はできません。代わりに、空のAMMの場合の特殊な入金を行う必要があります。 |
| `tecAMM_NOT_EMPTY` | トランザクションで`tfTwoAssetIfEmpty`が指定されましたが、AMMは空ではありませんでした。 | | `tecAMM_NOT_EMPTY` | トランザクションで`tfTwoAssetIfEmpty`が指定されましたが、AMMは空ではありませんでした。 |
| `tecAMM_FAILED` | 預け入れの条件が成立しませんでした。例えば、`EPrice`フィールドに指定された実効価格が低すぎる場合など。 | | `tecAMM_FAILED` | 預け入れの条件が成立しませんでした。例えば、`EPrice`フィールドに指定された実効価格が低すぎる場合など。 |
| `tecFROZEN` | トランザクションは[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているトークンを預けようとしました。 | | `tecFROZEN` | トランザクションは[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているトークンを預けようとした、またはプール内の資産の少なくとも1つがフリーズされています。 |
| `tecINSUF_RESERVE_LINE` | このトランザクションの送信者は、この処理による[準備金要件](../../../../concepts/accounts/reserves.md)の増加の対象であり、LPトークンを保持するための新しいトラストラインが必要で、そのための追加の所有者準備金分のXRPを保有していないためと思われます。 | | `tecINSUF_RESERVE_LINE` | このトランザクションの送信者は、この処理による[準備金要件](../../../../concepts/accounts/reserves.md)の増加の対象であり、LPトークンを保持するための新しいトラストラインが必要で、そのための追加の所有者準備金分のXRPを保有していないためと思われます。 |
| `tecUNFUNDED_AMM` | 送信者の残高が、指定された預け入れを行うのに十分な量ではありません。 | | `tecUNFUNDED_AMM` | 送信者の残高が、指定された預け入れを行うのに十分な量ではありません。 |
| `temBAD_AMM_TOKENS` | トランザクションでLPトークンを指定しましたが、`issuer`がAMMに紐づくAccountアドレスではない、または`currency`がこのAMMのLPトークンの通貨コードではない、またはトランザクションでこのAMMのLPトークンをAssetフィールドのいずれかに指定しました。 | | `temBAD_AMM_TOKENS` | トランザクションでLPトークンを指定しましたが、`issuer`がAMMに紐づくAccountアドレスではない、または`currency`がこのAMMのLPトークンの通貨コードではない、またはトランザクションでこのAMMのLPトークンをAssetフィールドのいずれかに指定しました。 |

View File

@@ -170,4 +170,4 @@ status: not_enabled
| `temINVALID_INNER_BATCH` | 内部トランザクションの形式が不正です。 | | `temINVALID_INNER_BATCH` | 内部トランザクションの形式が不正です。 |
| `temSEQ_AND_TICKET` | トランザクションに`TicketSequence`フィールドと、0以外の`Sequence`フィールドの両方が含まれています。両方を同時に指定することはできませんが、いずれか一方は必須です。 | | `temSEQ_AND_TICKET` | トランザクションに`TicketSequence`フィールドと、0以外の`Sequence`フィールドの両方が含まれています。両方を同時に指定することはできませんが、いずれか一方は必須です。 |
{% raw-partial file="/docs/_snippets/common-links.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -34,43 +34,46 @@ OfferCreateトランザクションは[分散型取引所](../../../../concepts/
{% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%}
| フィールド | JSONの型 | [内部の型][] | 説明 | | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 |
|:-----------------|:----------|:------------|:-----------| |:-----------------|:----------------------|:-------------|:---------|:-----------|
| [Expiration](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーの有効期限) | 数字 | UInt32 | _省略可_ オファーがアクティブでなくなるまでの時間([Rippleエポック以降の経過秒数][])。 | | `DomainID` | 文字列 - [ハッシュ][] | Hash256 | いいえ | 許可型DEXのレジャーエントリID。指定された場合、対応する[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用するパスを返します。([PermissionedDEX amendment][] {% not-enabled /%}が必要です。) |
| `OfferSequence` | 数 | UInt32 | _省略可_ 最初に削除されるオファー([OfferCancel][]と同様に指定されます)。 | | [`Expiration`](../../../../concepts/tokens/decentralized-exchange/offers.md#オファーの有効期限) | 数 | UInt32 | いいえ | オファーがアクティブでなくなるまでの時間([Rippleエポック以降の経過秒数][])。 |
| `TakerGets` | [通貨額][] | Amount | オファーの作成者によって作成される金額および通貨の種類。 | | `OfferSequence` | 整数 | UInt32 | いいえ | 最初に削除されるオファー([OfferCancel][]と同様に指定されます)。 |
| `TakerPays` | [通貨額][] | Amount | オファーの作成者によってリクエストされる金額および通貨の種類。 | | `TakerGets` | [通貨額][] | Amount | はい | オファーの作成者によって作成される金額および通貨の種類。 |
| `TakerPays` | [通貨額][] | Amount | はい | オファーの作成者によってリクエストされる金額および通貨の種類。 |
## OfferCreateフラグ ## OfferCreateフラグ
OfferCreate型のトランザクションについては、[`Flags`フィールド](../common-fields.md#flagsフィールド)で以下の値が追加でサポートされます。 OfferCreate型のトランザクションについては、[`Flags`フィールド](../common-fields.md#flagsフィールド)で以下の値が追加でサポートされます。
| フラグ名 | 16進数 | 10進数 | 説明 | | フラグ名 | 16進数 | 10進数 | 説明 |
|:----------------------|:-------------|:--------------|:-------------------| |:----------------------|:-------------|:--------------|:-------------------|
| `tfPassive` | `0x00010000` | 65536 | 有効な場合、オファーはオファー完全に約定するオファーを消費せず、代わりにレジャーのOfferオブジェクトになります。それはまだクロスしたオファーを消費します。 | | `tfPassive` | `0x00010000` | 65536 | このオファー完全に一致するオファーを約定しません。これにより、特定の値で交換レートを固定するオファーを台帳に設定できます。 |
| `tfImmediateOrCancel` | `0x00020000` | 131072 | オファーを[IOC注文](http://en.wikipedia.org/wiki/Immediate_or_cancel)として扱います。有効な場合、オファーはレジャーオブジェクトにはなりません。レジャー内の既存のオファーと約定させようとするだけです。即時にオファーがどのオファーとも約定しない場合、どの通貨とも取引せずに「正常に」実行します。この場合、トランザクションは`tesSUCCESS`の[結果コード](../transaction-results/index.md)を返しますが、レジャー内には、[Offerオブジェクト](../../ledger-data/ledger-entry-types/offer.md)を作成しません。 | | `tfImmediateOrCancel` | `0x00020000` | 131072 | オファーを[即時またはキャンセル注文](http://en.wikipedia.org/wiki/Immediate_or_cancel)として扱い、[Offerエントリ][]をオーダーブックに配置しません。トランザクションは、処理時に既存のオファーを約定し、可能な限り多くの取引を行います。 |
| `tfFillOrKill` | `0x00040000` | 262144 | オファーを[FOK注文](http://en.wikipedia.org/wiki/Fill_or_kill)として扱います。レジャー内の既存のオファーのみを約定しようとします。またこれは、全`TakerPays`の数量が取得できる場合に限られます。[fix1578 amendment][]が有効な場合でオファーを配置した時に実行できない場合、トランザクションは`tecKILLED`の[結果コード](../transaction-results/index.md)を返します。そうでない場合は、トランザクションは、どの通貨とも取り引きせずにキャンセルされた場合でも`tesSUCCESS`の結果コードを返します。 | | `tfFillOrKill` | `0x00040000` | 262144 | オファーを[即時またはキャンセル注文](http://en.wikipedia.org/wiki/Fill_or_kill)として扱い、[Offerエントリ][]をオーダーブックに配置しません。実行時に完全に約定できない場合、オファーをキャンセルします。デフォルトでは、所有者は完全な`TakerPays`の金額を受け取る必要があります。`tfSell`フラグが有効な場合、所有者は代わりに完全な`TakerGets`の金額を約定できる必要があります。 |
| `tfSell` | `0x00080000` | 524288 | 取引所で`TakerPays`Amountよりも多く取得することになっても、`TakerGets` Amountを交換します。 | | `tfSell` | `0x00080000` | 524288 | 取引所で`TakerPays`の金額よりも多く取得することになっても、`TakerGets`の金額を約定します。 |
| `tfHybrid` | `0x00100000` | 1048576 | 許可型DEXとオープンDEXの両方を使用できるハイブリッドオファーにします。このフラグを使用する場合、`DomainID`フィールドを指定する必要があります。 |
## エラーケース ## エラーケース
| エラーコード | 説明 | | エラーコード | 説明 |
|:-------------------------|:--------------------------------------------------| |:-------------------------|:--------------------------------------------------|
| `temINVALID_FLAG` | トランザクションが`tfImmediateOrCancel``tfFillOrKill`両方を指定した場合に発生します。|
| `tecEXPIRED` | トランザクションが指定した`Expiration`の時間が既に経過している場合に発生します。 |
| `tecKILLED` | トランザクションが`tfFillOrKill`を指定し、全額を約定できない場合に発生します。_[ImmediateOfferKilled amendment][]_ が有効な場合、この結果コードは、トランザクションが`tfImmediateOrCancel`を指定して資金が移動せずに実行された場合にも発生します(これまでは、これは`tesSUCCESS`を返していました)。 |
| `temBAD_EXPIRATION` | トランザクションの`Expiration`フィールドの値が無効なフォーマットの場合に発生します。 |
| `temBAD_SEQUENCE` | トランザクションの`OfferSequence`フィールドの値が無効なフォーマットであるか、トランザクション自身の`Sequence`番号より大きい場合に発生します。 |
| `temBAD_OFFER` | OfferがXRPとXRPを交換しようとした場合、またはトークンの無効な量やマイナスの量を交換しようとした場合に発生します。 |
| `temREDUNDANT` | トランザクションが同じトークン(同じ発行者、通貨コード)を指定した場合に発生します。 |
| `temBAD_CURRENCY` | トランザクションで通貨コードが"XRP"のトークンが指定された場合に発生します。 |
| `temBAD_ISSUER` | トランザクションが無効な`issuer`値を持つトークンを指定した場合に発生します。 |
| `tecNO_ISSUER` | トランザクションで、`issuer`の値が台帳の有効化されたアカウントでないトークンを指定した場合に発生します。|
| `tecFROZEN` | [フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトラストライン(ローカルおよびグローバルのフリーズを含む)上のトークンを含むトランザクションの場合に発生します。`TakerPays`(購入額)トークンが発行者によってディープフリーズされている場合に発生します。 |
| `tecUNFUNDED_OFFER` | トランザクションの送信者が`TakerGets`の通貨を正の値で保有していない場合に発生する。(例外: `TakerGets`にトランザクションの送信者が発行するトークンを指定した場合、トランザクションは成功します)。 |
| `tecNO_LINE` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、必要なトラストラインが存在しない場合に発生します。 |
| `tecNO_AUTH` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、トークンを受け取るトラストラインが存在するが認証されていない場合に発生します。 |
| `tecINSUF_RESERVE_OFFER` | 所有者が台帳に新しいOfferオブジェクトを追加するための準備要件を満たすのに十分なXRPを持っておらず、トランザクションがどの通貨も変換しなかった場合に発生します。(トランザクションが何らかの金額のトレードに成功した場合、トランザクションは結果コード`tesSUCCESS`で成功しますが、残りは台帳にOfferオブジェクトを作成しません)。 |
| `tecDIR_FULL` | トランザクションの送信者が台帳で多くのアイテムを所有している場合、またはオーダーブックに同じ取引レートのオファーがすでに多く含まれている場合に発生します。 | | `tecDIR_FULL` | トランザクションの送信者が台帳で多くのアイテムを所有している場合、またはオーダーブックに同じ取引レートのオファーがすでに多く含まれている場合に発生します。 |
| `tecEXPIRED` | トランザクションが指定した`Expiration`の時間が既に経過している場合に発生します。 |
| `tecFROZEN` | [フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトラストライン(ローカルおよびグローバルのフリーズを含む)上のトークンを含むトランザクションの場合に発生します。`TakerPays`(購入額)トークンが発行者によってディープフリーズされている場合に発生します。 |
| `tecINSUF_RESERVE_OFFER` | 所有者が台帳に新しいOfferオブジェクトを追加するための準備要件を満たすのに十分なXRPを持っておらず、トランザクションがどの通貨も変換しなかった場合に発生します。(トランザクションが何らかの金額のトレードに成功した場合、トランザクションは結果コード`tesSUCCESS`で成功しますが、残りは台帳にOfferオブジェクトを作成しません)。 |
| `tecKILLED` | トランザクションが`tfFillOrKill`を指定し、全額を約定できない場合に発生します。_[ImmediateOfferKilled amendment][]_ が有効な場合、この結果コードは、トランザクションが`tfImmediateOrCancel`を指定して資金が移動せずに実行された場合にも発生します(これまでは、これは`tesSUCCESS`を返していました)。 |
| `tecNO_AUTH` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、トークンを受け取るトラストラインが存在するが認証されていない場合に発生します。 |
| `tecNO_ISSUER` | トランザクションで、`issuer`の値が台帳の有効化されたアカウントでないトークンを指定した場合に発生します。|
| `tecNO_LINE` | 発行者が[Authorized Trust Lines](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使用しているトークンを含むトランザクションで、必要なトラストラインが存在しない場合に発生します。 |
| `tecNO_PERMISSION` | トランザクションが`DomainID`を使用しているが、送信者がそのドメインのメンバーではない場合に発生します。([PermissionedDEX amendment][] {% not-enabled /%}) |
| `tecUNFUNDED_OFFER` | トランザクションの送信者が`TakerGets`の通貨を正の値で保有していない場合に発生する。(例外: `TakerGets`にトランザクションの送信者が発行するトークンを指定した場合、トランザクションは成功します)。 |
| `temBAD_CURRENCY` | トランザクションで通貨コードが"XRP"のトークンが指定された場合に発生します。 |
| `temBAD_EXPIRATION` | トランザクションの`Expiration`フィールドの値が無効なフォーマットの場合に発生します。 |
| `temBAD_ISSUER` | トランザクションが無効な`issuer`値を持つトークンを指定した場合に発生します。 |
| `temBAD_OFFER` | OfferがXRPとXRPを交換しようとした場合、またはトークンの無効な量やマイナスの量を交換しようとした場合に発生します。 |
| `temBAD_SEQUENCE` | トランザクションの`OfferSequence`フィールドの値が無効なフォーマットであるか、トランザクション自身の`Sequence`番号より大きい場合に発生します。 |
| `temINVALID_FLAG` | トランザクションが`tfImmediateOrCancel``tfFillOrKill`両方を指定した場合に発生します。|
| `temREDUNDANT` | トランザクションが同じトークン(同じ発行者、通貨コード)を指定した場合に発生します。 |
{% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -8,7 +8,7 @@ labels:
- トークン - トークン
--- ---
# Payment # Payment
[[ソース]](https://github.com/XRPLF/rippled/blob/5425a90f160711e46b2c1f1c93d68e5941e4bfb6/src/ripple/app/transactors/Payment.cpp "ソース") [[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/tx/detail/Payment.cpp "ソース")
Paymentトランザクションは、アカウント間での価値の移動を表現するものです(通過するパスによっては、非可分的に発生する追加的な価値交換を伴うことがあります)。このトランザクションタイプはいくつかの[支払いの種類](#paymentの種類)に使用することがでできます。 Paymentトランザクションは、アカウント間での価値の移動を表現するものです(通過するパスによっては、非可分的に発生する追加的な価値交換を伴うことがあります)。このトランザクションタイプはいくつかの[支払いの種類](#paymentの種類)に使用することがでできます。
@@ -37,17 +37,18 @@ Paymentは、[アカウントを作成](#アカウントの作成)する唯一
{% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%}
| フィールド | JSONの型 | [内部の型][] | 説明 | | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 |
| :--------------- | :------------------ | :----------- | ---- | | :--------------- | :-------------------- | :----------- | :---------- | :---- |
| `Amount` | [通貨額][] | Amount | `DeliverMax`のエイリアス | | `Amount` | [通貨額][] | Amount | APIv1: はい | `DeliverMax`のエイリアス |
| `CredentialIDs` | 文字列の配列 | Vector256 | このトランザクションによって作成される入金を承認するための、受取人によって事前承認された資格証明のセット。配列の各メンバは、レジャーのCredentialエントリのレジャーエントリIDでなければなりません。(_[**Credentials** amendment](../../../../../resources/known-amendments.md#credentials)が必要です。_ {% not-enabled /%}) | | `CredentialIDs` | 文字列の配列 | Vector256 | いいえ | このトランザクションによって作成される入金を承認するための、受取人によって事前承認された資格証明のセット。配列の各メンバは、レジャーのCredentialエントリのレジャーエントリIDでなければなりません。(_[**Credentials** amendment](../../../../../resources/known-amendments.md#credentials)が必要です。_ {% not-enabled /%}) |
| `DeliverMax` | [Currency Amount][] | Amount | [API v2][]: 送金する通貨額。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。[**tfPartialPayment**フラグ](#paymentのフラグ)が設定されている場合は、この金額を _上限_ とする金額を送金します。 {% badge href="https://github.com/XRPLF/rippled/releases/tag/2.0.0" %}新規: rippled 2.0.0{% /badge %} | | `DeliverMax` | [通貨額][] | Amount | はい | [API v2][]: 送金する通貨額。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。[**tfPartialPayment**フラグ](#paymentのフラグ)が設定されている場合は、この金額を _上限_ とする金額を送金します。 {% badge href="https://github.com/XRPLF/rippled/releases/tag/2.0.0" %}新規: rippled 2.0.0{% /badge %} |
| `DeliverMin` | [通貨額][] | Amount | _省略可_ このトランザクションで送金する、宛先通貨での最少金額。[Partial Payments](../../../../concepts/payment-types/partial-payments.md)の場合のみ有効になります。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。 | | `DeliverMin` | [通貨額][] | Amount | いいえ | _省略可_ このトランザクションで送金する、宛先通貨での最少金額。[Partial Payments](#partial-payments)の場合のみ有効になります。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。 |
| `Destination` | 文字列 | AccountID | 支払いを受取るアカウントの一意アドレス。 | | `Destination` | 文字列 - [アドレス][] | AccountID | はい | 支払いを受取るアカウントの一意アドレス。 |
| `DestinationTag` | 数値 | UInt32 | _省略可_ 宛先(支払先となる、ホスティングされている受取人)への支払い理由を明確にするための任意のタグ。 | | `DestinationTag` | 数値 | UInt32 | いいえ | 宛先(支払先となる、ホスティングされている受取人)への支払い理由を明確にするための任意のタグ。 |
| `InvoiceID` | 文字列 | UInt256 | _省略可_ この支払いの具体的な理由または識別子を表現する任意の256ビットハッシュ。 | | `DomainID` | String - [Hash][] | Hash256 | いいえ | 許可されたドメインのレジャーエントリID。クロスカレンシー支払いの場合は、通貨を変換するために、対応する[許可されたDEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)のみを使用してください。送信者と受取人の両方が、指定されたドメインへのアクセスを許可する有効な資格証明を持っている必要があります。このフィールドは、クロスカレンシー支払いではない場合は効果がありません。(_[**PermissionedDEX** amendment][]が必要です。_ {% not-enabled /%}) |
| `Paths` | パス配列の配列 | PathSet | (省略可。自動入力可能)このトランザクションに使用される[支払いパス](../../../../concepts/tokens/fungible-tokens/paths.md)の配列。XRP間のトランザクションでは省略する必要があります。 | | `InvoiceID` | 文字列 - 16進文字 | UInt256 | いいえ | この支払いの具体的な理由または識別子を表現する任意の256ビットハッシュ。 |
| `SendMax` | [通貨額][] | Amount | _省略可_ [送金手数料](../../../../concepts/tokens/transfer-fees.md)、為替レート、[スリッページ](http://en.wikipedia.org/wiki/Slippage_%28finance%29)を含め、このトランザクションに関して支払い元通貨での負担を許容する上限額。[トランザクションの送信コストとしてバーンされるXRP](../../../../concepts/transactions/transaction-cost.md)は含めないでください。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。クロスカレンシー支払いまたは複数のトークンを伴う支払いについては、このフィールドを入力する必要があります。XRP間の支払いでは省略する必要があります。 | | `Paths` | パス配列の配列 | PathSet | いいえ | _自動入力可能_ このトランザクションに使用される[支払いパス](../../../../concepts/tokens/fungible-tokens/paths.md)の配列。XRP間のトランザクションでは省略する必要があります。 |
| `SendMax` | [通貨額][] | Amount | いいえ | [送金手数料](../../../../concepts/tokens/transfer-fees.md)、為替レート、[スリッページ](http://en.wikipedia.org/wiki/Slippage_%28finance%29)を含め、このトランザクションに関して支払い元通貨での負担を許容する上限額。[トランザクションの送信コストとしてバーンされるXRP](../../../../concepts/transactions/transaction-cost.md)は含めないでください。XRP以外の金額の場合、入れ子フィールドの名前では、アルファベットの小文字のみ使用してください。クロスカレンシー支払いまたは複数のトークンを伴う支払いについては、このフィールドを入力する必要があります。XRP間の支払いでは省略する必要があります。 |
トランザクションを指定する際は、`Amount`または`DeliverMax`のいずれかを指定する必要がありますが、両方を指定することはできません。JSONでトランザクションを表示する場合、API v1では常に`Amount`を使用し、API v2以降では常に`DeliverMax`を使用します。 トランザクションを指定する際は、`Amount`または`DeliverMax`のいずれかを指定する必要がありますが、両方を指定することはできません。JSONでトランザクションを表示する場合、API v1では常に`Amount`を使用し、API v2以降では常に`DeliverMax`を使用します。
@@ -62,7 +63,7 @@ Paymentトランザクションタイプは、いくつかの異なるタイプ
| [クロスカレンシー(通貨間)決済][] | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 通常は必須 | いいえ | 発行された通貨を保有者から別の保有者に送信します。`Amount``SendMax`の両方をXRPにすることはできません。これらの支払いは、発行者を介して[リップリング](../../../../concepts/tokens/fungible-tokens/rippling.md)し、トランザクションがパスセットを指定した場合、複数の仲介者を介してより長い[パス](../../../../concepts/tokens/fungible-tokens/paths.md)を取ることができます。トランザクション形式には、発行者が設定した[送金手数料](../../../../concepts/tokens/transfer-fees.md) が適用されます。これらのトランザクションは、異なる通貨間や、場合によっては同じ通貨コードで異なる発行者の通貨間を接続するために、[分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)のオファーを利用します。 | | [クロスカレンシー(通貨間)決済][] | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 通常は必須 | いいえ | 発行された通貨を保有者から別の保有者に送信します。`Amount``SendMax`の両方をXRPにすることはできません。これらの支払いは、発行者を介して[リップリング](../../../../concepts/tokens/fungible-tokens/rippling.md)し、トランザクションがパスセットを指定した場合、複数の仲介者を介してより長い[パス](../../../../concepts/tokens/fungible-tokens/paths.md)を取ることができます。トランザクション形式には、発行者が設定した[送金手数料](../../../../concepts/tokens/transfer-fees.md) が適用されます。これらのトランザクションは、異なる通貨間や、場合によっては同じ通貨コードで異なる発行者の通貨間を接続するために、[分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)のオファーを利用します。 |
| [Partial payment][] | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 通常は必須 | いいえ | 任意の通貨を特定の金額まで送ります。[`tfPartialPayment` フラグ](#paymentのフラグ)を使用します。トランザクションが成功するための最小値を指定する `DeliverMin` 値を含めることができます。トランザクションが `DeliverMin` を指定しない場合、_任意の正の値_ を指定して成功させることができる。 | | [Partial payment][] | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 通常は必須 | いいえ | 任意の通貨を特定の金額まで送ります。[`tfPartialPayment` フラグ](#paymentのフラグ)を使用します。トランザクションが成功するための最小値を指定する `DeliverMin` 値を含めることができます。トランザクションが `DeliverMin` を指定しない場合、_任意の正の値_ を指定して成功させることができる。 |
| 通貨変換 | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 必須 | はい | [分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)のオファーを消費して、ある通貨を別の通貨に交換し、[裁定取引](https://ja.wikipedia.org/wiki/%E8%A3%81%E5%AE%9A%E5%8F%96%E5%BC%95)の機会を得ることが出来ます。`Amount``SendMax` の両方を XRP にすることはできません。[Data API](../../../data-api.md) は、このタイプの取引を "payment" ではなく、"exchange" として追跡しています。 | | 通貨変換 | オブジェクト (非XRP) / 文字列 (XRP) | オブジェクト (非XRP) / 文字列 (XRP) | 必須 | はい | [分散型取引所](../../../../concepts/tokens/decentralized-exchange/index.md)のオファーを消費して、ある通貨を別の通貨に交換し、[裁定取引](https://ja.wikipedia.org/wiki/%E8%A3%81%E5%AE%9A%E5%8F%96%E5%BC%95)の機会を得ることが出来ます。`Amount``SendMax` の両方を XRP にすることはできません。[Data API](../../../data-api.md) は、このタイプの取引を "payment" ではなく、"exchange" として追跡しています。 |
| MPTの支払い | オブジェクト | 省略 | 省略 | はい | MPTを保有者に送信します。[MPTの支払い](#mpt-payments)をご覧ください。 | | MPTの支払い | オブジェクト | 省略 | 省略 | いいえ | MPTを保有者に送信します。[MPTの支払い](#mpt-payments)をご覧ください。 |
[XRP同士の直接支払い]: ../../../../concepts/payment-types/direct-xrp-payments.md [XRP同士の直接支払い]: ../../../../concepts/payment-types/direct-xrp-payments.md
[発行通貨の作成・償還]: ../../../../concepts/tokens/index.md [発行通貨の作成・償還]: ../../../../concepts/tokens/index.md
@@ -74,11 +75,11 @@ Paymentトランザクションタイプは、いくつかの異なるタイプ
ほとんどの場合、XRP以外の[通貨額][]の`issuer`フィールドは、金融機関の[発行アドレス](../../../../concepts/accounts/account-types.md)を示しています。ただし、支払いを記述するにあたって、支払いの`Amount`フィールドと`SendMax`フィールドにある`issuer`フィールドについては、特殊なルールが存在します。 ほとんどの場合、XRP以外の[通貨額][]の`issuer`フィールドは、金融機関の[発行アドレス](../../../../concepts/accounts/account-types.md)を示しています。ただし、支払いを記述するにあたって、支払いの`DeliverMax`(または`Amount`)フィールドと`SendMax`フィールドにある`issuer`フィールドについては、特殊なルールが存在します。
* 2つのアドレス間で、同一の通貨に関して存在する残高は常に1つです。つまり、金額の`issuer`フィールドが実際に表しているのは、イシュアンスを作成したアドレスではなく、イシュアンスを換金する相手方であることがあります。 * 2つのアドレス間で、同一の通貨に関して存在する残高は常に1つです。つまり、金額の`issuer`フィールドが実際に表しているのは、イシュアンスを作成したアドレスではなく、イシュアンスを換金する相手方であることがあります。
* 宛先`Amount`フィールドの`issuer`フィールドが`Destination`アドレスと一致している場合、「宛先が受け入れるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。これには、他のトラストラインで保持されている宛先によって作成されたイシュアンスに加え、宛先が当該アドレスまでトラストラインを延長しているすべてのアドレスが含まれます。 * 宛先`DeliverMax`フィールドの`issuer`フィールドが`Destination`アドレスと一致している場合、「宛先が受け入れるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。これには、他のトラストラインで保持されている宛先によって作成されたイシュアンスに加え、宛先が当該アドレスまでトラストラインを延長しているすべてのアドレスが含まれます。
* `SendMax`フィールドの`issuer`フィールドが送信元アカウントのアドレスと一致している場合、「送信元が使用できるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。これには、他のアカウントが送信元アカウントまで延長しているトラストラインで新しいイシュアンスを作成すること、送信元アカウントが保持しているイシュアンスを他のイシュアーから送信することが含まれます。 * `SendMax`フィールドの`issuer`フィールドが送信元アカウントのアドレスと一致している場合、「送信元が使用できるあらゆるイシュアー」を意味する特殊なケースとして取り扱われます。送信元アカウントが既に保有しているトークンを送信するか、送信元アカウントと信頼関係にある他のユーザーに対して新しいトークンを発行することができます。
## アカウントの作成 ## アカウントの作成
@@ -108,7 +109,7 @@ Payment型のトランザクションについては、[`Flags`フィールド](
| フラグの名前 | 16進値 | 10進値 | 説明 | | フラグの名前 | 16進値 | 10進値 | 説明 |
| :----------------- | :----------- | :----- | ---- | | :----------------- | :----------- | :----- | ---- |
| `tfNoRippleDirect` | `0x00010000` | 65536 | デフォルトパスを使用せず、`Paths`フィールドに含まれているパスのみ使用します。これによりトランザクションは強制的に裁定機会を活用することになります。ほとんどのクライアントでは、これは必要ありません。 | | `tfNoRippleDirect` | `0x00010000` | 65536 | デフォルトパスを使用せず、`Paths`フィールドに含まれているパスのみ使用します。これによりトランザクションは強制的に裁定機会を活用することになります。ほとんどのクライアントでは、これは必要ありません。 |
| `tfPartialPayment` | `0x00020000` | 131072 | `SendMax`を超えていないのに指定された`Amount`を送金できない場合、即座に失敗とするのではなく、受取られる額を減額します。詳細は、[Partial Payments](../../../../concepts/payment-types/partial-payments.md)をご覧ください。 | | `tfPartialPayment` | `0x00020000` | 131072 | `SendMax`を超えていないのに指定された`Amount`を送金できない場合、即座に失敗とするのではなく、受取られる額を減額します。詳細は、[Partial Payments](#partial-payments)をご覧ください。 |
| `tfLimitQuality` | `0x00040000` | 262144 | すべての変換で、入力と出力との比率が`Amount``SendMax`との比率と同一であるか、さらに有利となるパスのみを採用します。詳細は、[クオリティの制限](#クオリティの制限)をご覧ください。 | | `tfLimitQuality` | `0x00040000` | 262144 | すべての変換で、入力と出力との比率が`Amount``SendMax`との比率と同一であるか、さらに有利となるパスのみを採用します。詳細は、[クオリティの制限](#クオリティの制限)をご覧ください。 |
## Partial Payments ## Partial Payments
@@ -184,6 +185,10 @@ _([Credentials amendment][]が必要です。 {% not-enabled /%})_
提供された資格証明が、Deposit Authorizationを使用していないアカウントに対して提供されている場合、資格証明は不要ですが、有効性は依然としてチェックされます。 提供された資格証明が、Deposit Authorizationを使用していないアカウントに対して提供されている場合、資格証明は不要ですが、有効性は依然としてチェックされます。
{% admonition type="info" name="注記" %}
`CredentialIDs`フィールドは、デポジットの承認処理にのみ使用され、[許可型DEX](../../../../concepts/tokens/decentralized-exchange/permissioned-dexes.md)での取引には使用されません。ただし、許可型DEXでもアクセス権限を付与するために認証情報が使用されます。許可型DEXで取引を行うには、`DomainID`フィールドを使用して、有効な資格情報を保持しているドメインを指定する必要があります。
{% /admonition %}
## 準備金を下回るアカウントに対する特別な送金のケース ## 準備金を下回るアカウントに対する特別な送金のケース

View File

@@ -45,4 +45,4 @@ _([PermissionedDomains amendment][]が必要です {% not-enabled /%})_
| `tecNO_ENTRY` | `DomainID`フィールドで指定された許可型ドメインがレジャーに存在しません。 | | `tecNO_ENTRY` | `DomainID`フィールドで指定された許可型ドメインがレジャーに存在しません。 |
| `temDISABLED` | `PermissionedDomains` amendmentが有効ではありません。 | | `temDISABLED` | `PermissionedDomains` amendmentが有効ではありません。 |
{% raw-partial file="/docs/_snippets/common-links.md" /%} {% raw-partial file="/@l10n/ja/docs/_snippets/common-links.md" /%}

View File

@@ -44,7 +44,7 @@ _[XChainBridge Amendment][] {% not-enabled /%} が必要です_
## XChainModifyBridgeのフィールド ## XChainModifyBridgeのフィールド
| フィールド | JSONの型 | [内部の型][] | 必須? | 説明 | | フィールド | JSONの型 | [内部の型][] | 必須? | 説明 |
|:-------------------------|:-------------|:-------- -----|:------|-----| |:-------------------------|:-------------|:--------------|:------|-----|
| `Flags` | 数値 | UInt32 | はい | このトランザクションのフラグを指定します。 | | `Flags` | 数値 | UInt32 | はい | このトランザクションのフラグを指定します。 |
| `MinAccountCreateAmount` | [通貨額][] | Amount | いいえ | `XChainAccountCreateCommit`トランザクションに必要な最小金額。このフィールドが存在しない場合、`XChainAccountCreateCommit`トランザクションは失敗します。このフィールドはXRP-XRPブリッジにのみ存在できます。 | | `MinAccountCreateAmount` | [通貨額][] | Amount | いいえ | `XChainAccountCreateCommit`トランザクションに必要な最小金額。このフィールドが存在しない場合、`XChainAccountCreateCommit`トランザクションは失敗します。このフィールドはXRP-XRPブリッジにのみ存在できます。 |
| `SignatureReward` | [通貨額][] | Amount | いいえ | Witnessサーバに支払う署名の報酬の合計額。この金額は署名者の間で分配されます。 | | `SignatureReward` | [通貨額][] | Amount | いいえ | Witnessサーバに支払う署名の報酬の合計額。この金額は署名者の間で分配されます。 |

View File

@@ -829,6 +829,9 @@ resources.dev-tools.websocket-api.curl.modal.desc.part2: を使用してこれ
API Methods: APIメソッド API Methods: APIメソッド
Methods: メソッド Methods: メソッド
Examples: の例 Examples: の例
# resources/dev-tools/websocket-api/ClioOnly.tsx
resources.dev-tools.websocket-api.clio-only-badge: Clioのみ
resources.dev-tools.websocket-api.clio-only-tooltip: このメソッドはClioサーバーからのみ利用可能です。
# resources/dev-tools/xrp-ledger-toml-checker.page.tsx # resources/dev-tools/xrp-ledger-toml-checker.page.tsx
resources.dev-tools.toml-checker.p.part1: もしあなたがXRP Ledgerバリデータを運営していたり、XRP Ledgerをビジネスで利用しているのであれば、XRP Ledgerの利用状況に関する情報を、機械読み取り可能な resources.dev-tools.toml-checker.p.part1: もしあなたがXRP Ledgerバリデータを運営していたり、XRP Ledgerをビジネスで利用しているのであれば、XRP Ledgerの利用状況に関する情報を、機械読み取り可能な

View File

@@ -11,145 +11,155 @@ ul.nav.navbar-nav {
flex-grow: 1; flex-grow: 1;
} }
:root { .clio-only-notice {
background-color: var(--admonition-info-bg-color);
margin-left: var(--spacing-sm);
padding: var(--spacing-xs);
border-radius: var(--border-radius);
}
:root, :root.dark {
--navbar-height: 80px;
/* XRPL color palette; match to styles/_colors.scss /* XRPL color palette; match to styles/_colors.scss
Some colors don't have a 10 equivalent so 9 is repeated. Some colors don't have a 10 equivalent so 9 is repeated.
Note, at present these variables are mostly overridden by These are in reverse order of the ones in styles/_colors.scss
styled-components variables which are in reverse order, so so that they correspond to the same-named variables provided by
we can't actually use these variables as-is. styled-components as part of Redocly.
*/ */
/* Redocly doesn't have vars for grays by default */ /* Redocly doesn't have vars for grays by default */
--color-gray-1: #F5F5F7; --color-gray-1: #111112;
--color-gray-2: #E0E0E1; --color-gray-2: #232325;
--color-gray-3: #C1C1C2; --color-gray-3: #343437;
--color-gray-4: #A2A2A4; --color-gray-4: #454549;
--color-gray-5: #838386; --color-gray-5: #838386;
--color-gray-6: #454549; --color-gray-6: #A2A2A4;
--color-gray-7: #343437; --color-gray-7: #C1C1C2;
--color-gray-8: #232325; --color-gray-8: #E0E0E1;
--color-gray-9: #111112; --color-gray-9: #F5F5F7;
--color-gray-10: var(--color-gray-9); --color-gray-10: var(--color-gray-9);
/* color-red = XRPL $magenta */ /* color-red = XRPL $magenta */
--color-red-1: #FFE5F2; --color-red-1: #4C0026;
--color-red-2: #FFB2D8; --color-red-2: #4C0026;
--color-red-3: #FF80BF; --color-red-3: #80003F;
--color-red-4: #FF4BA4; --color-red-4: #B20058;
--color-red-5: #FF198B; --color-red-5: #E50071;
--color-red-6: #E50071; --color-red-6: #FF198B;
--color-red-7: #B20058; --color-red-7: #FF4BA4;
--color-red-8: #80003F; --color-red-8: #FF80BF;
--color-red-9: #4C0026; --color-red-9: #FFB2D8;
--color-red-10: #4C0026; --color-red-10: #FFE5F2;
/* color-green = XRPL $green */ /* color-green = XRPL $green */
--color-green-1: #D6FAE7; --color-green-1: #0A2E1B;
--color-green-2: #ADF5CE; --color-green-2: #145C35;
--color-green-3: #84F0B6; --color-green-3: #1E8A50;
--color-green-4: #5BEB9D; --color-green-4: #28B86A;
--color-green-5: #32E685; --color-green-5: #2DCF78;
--color-green-6: #2DCF78; --color-green-6: #32E685;
--color-green-7: #28B86A; --color-green-7: #5BEB9D;
--color-green-8: #1E8A50; --color-green-8: #84F0B6;
--color-green-9: #145C35; --color-green-9: #ADF5CE;
--color-green-10: #0A2E1B; --color-green-10: #D6FAE7;
/* color-gold = XRPL $yellow */ /* color-gold = XRPL $yellow */
--color-gold-1: #FEFFE5; --color-gold-1: #4B4C00;
--color-gold-2: #FDFFB2; --color-gold-2: #4B4C00;
--color-gold-3: #FCFF80; --color-gold-3: #7D8000;
--color-gold-4: #FBFF4C; --color-gold-4: #AEB200;
--color-gold-5: #FAFF19; --color-gold-5: #E0E500;
--color-gold-6: #E0E500; --color-gold-6: #FAFF19;
--color-gold-7: #AEB200; --color-gold-7: #FBFF4C;
--color-gold-8: #7D8000; --color-gold-8: #FCFF80;
--color-gold-9: #4B4C00; --color-gold-9: #FDFFB2;
--color-gold-10: #4B4C00; --color-gold-10: #FEFFE5;
/* color-blue = XRPL $blue */ /* color-blue = XRPL $blue */
--color-blue-1: #E5F5FF; --color-blue-1: #001133;
--color-blue-2: #B2E0FF; --color-blue-2: #002E4C;
--color-blue-3: #80CCFF; --color-blue-3: #004D80;
--color-blue-4: #4BB7FF; --color-blue-4: #006BB2;
--color-blue-5: #19A3FF; --color-blue-5: #008AE5;
--color-blue-6: #008AE5; --color-blue-6: #19A3FF;
--color-blue-7: #006BB2; --color-blue-7: #4BB7FF;
--color-blue-8: #004D80; --color-blue-8: #80CCFF;
--color-blue-9: #002E4C; --color-blue-9: #B2E0FF;
--color-blue-10: #001133; --color-blue-10: #E5F5FF;
/* color purple = XRPL $blue-purple */ /* color purple = XRPL $blue-purple */
--color-purple-1: #F0E5FF; --color-purple-1: #20004C;
--color-purple-2: #D2B2FF; --color-purple-2: #20004C;
--color-purple-3: #B480FF; --color-purple-3: #350080;
--color-purple-4: #9A52FF; --color-purple-4: #4A00B2;
--color-purple-5: #7919FF; --color-purple-5: #5F00E5;
--color-purple-6: #5F00E5; --color-purple-6: #7919FF;
--color-purple-7: #4A00B2; --color-purple-7: #9A52FF;
--color-purple-8: #350080; --color-purple-8: #B480FF;
--color-purple-9: #20004C; --color-purple-9: #D2B2FF;
--color-purple-10: #20004C; --color-purple-10: #F0E5FF;
/* color-magenta = XRPL $red-purple */ /* color-magenta = XRPL $red-purple */
--color-magenta-1: #FBE5FF; --color-magenta-1: #40004C;
--color-magenta-2: #F2B2FF; --color-magenta-2: #40004C;
--color-magenta-3: #EA80FF; --color-magenta-3: #6B0080;
--color-magenta-4: #E24CFF; --color-magenta-4: #9500B2;
--color-magenta-5: #D919FF; --color-magenta-5: #C000E5;
--color-magenta-6: #C000E5; --color-magenta-6: #D919FF;
--color-magenta-7: #9500B2; --color-magenta-7: #E24CFF;
--color-magenta-8: #6B0080; --color-magenta-8: #EA80FF;
--color-magenta-9: #40004C; --color-magenta-9: #F2B2FF;
--color-magenta-10: #40004C; --color-magenta-10: #FBE5FF;
/* XRPL doesn't have a color-cyan equivalent /* XRPL doesn't have a color-cyan equivalent*
--color-cyan-1: #e6fffb; --color-cyan-1: #002329;*
--color-cyan-2: #b5f5ec; --color-cyan-2: #00474f;*
--color-cyan-3: #87e8de; --color-cyan-3: #006d75;*
--color-cyan-4: #5cdbd3; --color-cyan-4: #08979c;*
--color-cyan-5: #36cfc9; --color-cyan-5: #13c2c2;*
--color-cyan-6: #13c2c2; --color-cyan-6: #36cfc9;*
--color-cyan-7: #08979c; --color-cyan-7: #5cdbd3;*
--color-cyan-8: #006d75; --color-cyan-8: #87e8de;*
--color-cyan-9: #00474f; --color-cyan-9: #b5f5ec;*
--color-cyan-10: #002329; */ --color-cyan-10: #e6fffb; */
/* color-yellow = XRPL $yellow */ /* color-yellow = XRPL $yellow */
--color-yellow-1: #FEFFE5; --color-yellow-1: #4B4C00;
--color-yellow-2: #FDFFB2; --color-yellow-2: #4B4C00;
--color-yellow-3: #FCFF80; --color-yellow-3: #7D8000;
--color-yellow-4: #FBFF4C; --color-yellow-4: #AEB200;
--color-yellow-5: #FAFF19; --color-yellow-5: #E0E500;
--color-yellow-6: #E0E500; --color-yellow-6: #FAFF19;
--color-yellow-7: #AEB200; --color-yellow-7: #FBFF4C;
--color-yellow-8: #7D8000; --color-yellow-8: #FCFF80;
--color-yellow-9: #4B4C00; --color-yellow-9: #FDFFB2;
--color-yellow-10: #4B4C00; --color-yellow-10: #FEFFE5;
/* XRPL doesn't have a color-lime equivalent /* XRPL doesn't have a color-lime equivalent*
--color-lime-1: #fcffe6; --color-lime-1: #254000;*
--color-lime-2: #f4ffb8; --color-lime-2: #3f6600;*
--color-lime-3: #eaff8f; --color-lime-3: #5b8c00;*
--color-lime-4: #d3f261; --color-lime-4: #7cb305;*
--color-lime-5: #bae637; --color-lime-5: #a0d911;*
--color-lime-6: #a0d911; --color-lime-6: #bae637;*
--color-lime-7: #7cb305; --color-lime-7: #d3f261;*
--color-lime-8: #5b8c00; --color-lime-8: #eaff8f;*
--color-lime-9: #3f6600; --color-lime-9: #f4ffb8;*
--color-lime-10: #254000; */ --color-lime-10: #fcffe6; */
/* XRPL doesn't have a color-geekblue equivalent /* XRPL doesn't have a color-geekblue equivalent*
--color-geekblue-1: #f0f5ff; --color-geekblue-1: #030852;*
--color-geekblue-2: #d6e4ff; --color-geekblue-2: #061178;*
--color-geekblue-3: #adc6ff; --color-geekblue-3: #10239e;*
--color-geekblue-4: #85a5ff; --color-geekblue-4: #1d39c4;*
--color-geekblue-5: #597ef7; --color-geekblue-5: #2f54eb;*
--color-geekblue-6: #2f54eb; --color-geekblue-6: #597ef7;*
--color-geekblue-7: #1d39c4; --color-geekblue-7: #85a5ff;*
--color-geekblue-8: #10239e; --color-geekblue-8: #adc6ff;*
--color-geekblue-9: #061178; --color-geekblue-9: #d6e4ff;*
--color-geekblue-10: #030852; */ --color-geekblue-10: #f0f5ff; */
/* Dark mode colors by default */ /* Dark mode colors by default */
--color-primary-bg: var(--color-gray-10); --color-primary-bg: var(--color-gray-10);
@@ -162,30 +172,30 @@ ul.nav.navbar-nav {
--color-primary-text-hover: #201dad; --color-primary-text-hover: #201dad;
--color-primary-text: #161087; --color-primary-text: #161087;
--color-primary-text-active: #0d086e;*/ --color-primary-text-active: #0d086e;*/
--link-color-primary: #fff; --link-color-primary: white;
--link-decoration: underline; --link-decoration: underline;
--link-font-weight: var(--font-weight-regular); --link-font-weight: var(--font-weight-regular);
--link-color-primary-hover: #9a52ff; --link-color-primary-hover: var(--color-purple-7)
--link-decoration-hover: underline; --link-decoration-hover: underline;
--link-color-visited: #fff; --link-color-visited: white;
--link-visited-decoration: underline; --link-visited-decoration: underline;
--bg-color: var(--color-gray-10); --bg-color: var(--color-gray-10);
--bg-color-raised: var(--color-gray-8); --bg-color-raised: var(--color-gray-2);
--background-color: var(--bg-color); --background-color: var(--bg-color);
--font-family-base: 'Work Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; --font-family-base: 'Work Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
--heading-font-family: var(--font-family-base); --heading-font-family: var(--font-family-base);
--inline-code-font-family: "Space Mono", monospace; --inline-code-font-family: "Space Mono", monospace;
--inline-code-text-color: #5beb9d; /* $green-400 */ --inline-code-text-color: var(--color-green-7);
--inline-code-bg-color: #0a2e1b; /* $green-1000 */ --inline-code-bg-color: var(--color-green-1);
--inline-code-border-radius: 0; --inline-code-border-radius: 0;
--heading-anchor-color: #9a52ff; --heading-anchor-color: var(--color-purple-7);
--h1-font-size: 3rem; --h1-font-size: 3rem;
--h2-font-size: 2.5rem; --h2-font-size: 2.5rem;
--h3-font-size: 2.125rem; --h3-font-size: 2.125rem;
@@ -195,14 +205,18 @@ ul.nav.navbar-nav {
--h5-font-size: 1.25rem; --h5-font-size: 1.25rem;
--h5-line-height: 1.5rem; --h5-line-height: 1.5rem;
--menu-container-padding-top: 0;
--md-content-padding: 4px 0;
--toc-offset-top: 2px;
--sidebar-border-color: transparent; --sidebar-border-color: transparent;
--sidebar-bg-color: transparent; --sidebar-bg-color: transparent;
--sidebar-margin-horizontal: 32px; --sidebar-margin-horizontal: 32px;
--border-radius-md: 4px; --border-radius-md: 4px;
--code-block-bg-color: #232325; --code-block-bg-color: var(--color-gray-2);
--code-block-controls-bg-color: #232325; --code-block-controls-bg-color: var(--color-gray-2);
--code-block-controls-border: none; --code-block-controls-border: none;
--code-block-padding: 0 2rem 1.5rem 2rem; --code-block-padding: 0 2rem 1.5rem 2rem;
@@ -216,62 +230,111 @@ ul.nav.navbar-nav {
--footer-border-color: transparent; --footer-border-color: transparent;
--footer-title-font-weight: 600; --footer-title-font-weight: 600;
--footer-title-font-size: 1rem; --footer-title-font-size: 1rem;
--footer-title-text-color: #A2A2A4; --footer-title-text-color: var(--color-gray-6);
--menu-item-padding-horizontal: 0px; --menu-item-padding-horizontal: 0px;
--md-list-left-padding: 40px; --md-list-left-padding: 40px;
--md-table-header-bg-color: #32343E; --md-list-margin: 0 0 20px 0;
--md-table-border-color: #32343E; --md-table-header-bg-color: var(--color-gray-3);
--md-table-border-color: var(--color-gray-3);
--md-tabs-content-padding: 0; --md-tabs-content-padding: 0;
--md-tabs-tab-wrapper-padding: 0;
--text-color-helper: var(--color-gray-6);
--color-text-primary: white;
--button-color-hover: white;
--text-color-secondary: var(--color-gray-9); /* inherited for adominition text color */
--admonition-success-bg-color: var(--color-green-2);
--admonition-info-bg-color: var(--color-blue-4);
/* none of the yellow shades in the XRPL palette work well with "warning"
admonitions, so leave it the default */
--admonition-danger-bg-color: var(--color-red-3);
} }
:root.light { :root.light {
--link-color-primary-hover: #4A00B2; --link-color-primary-hover: var(--color-purple-4);
--link-color-visited: #000; --link-color-visited: black;
--text-color-secondary: #000; --text-color-secondary: black;
--code-block-bg-color: #E0E0E1; --code-block-bg-color: var(--color-gray-8);
--code-block-controls-bg-color: #E0E0E1; --code-block-controls-bg-color: var(--color-gray-8);
--code-block-controls-border: none; --code-block-controls-border: none;
--md-tabs-active-tab-bg-color: #C1C1C2; --md-tabs-active-tab-bg-color: var(--color-gray-7);
--code-block-tokens-function-color: #B23C00;
--code-block-tokens-operator-color: #000;
--code-block-tokens-comment-color: #343437;
--code-block-tokens-string-color: #145C35;
--inline-code-bg-color: #E0E0E1;
--search-trigger-bg-color: #E0E0E1; --inline-code-bg-color: var(--color-gray-8);
--search-trigger-color: #838386;
--language-picker-border-color: #C1C1C2; --search-trigger-bg-color: var(--color-gray-8);
--language-picker-background-color: #E0E0E1; --search-trigger-color: var(--color-gray-5);
--select-list-bg-color: #E0E0E1; --modal-bg-color: var(--color-gray-9);
--footer-title-text-color: #000; --language-picker-border-color: var(--color-gray-7);
--bg-color: var(--color-gray-1); --language-picker-background-color: var(--color-gray-8);
--bg-color-raised: var(--color-gray-2); --select-list-bg-color: var(--color-gray-8);
--button-content-color-link: #000;
--md-table-header-bg-color: var(--color-gray-2); --footer-title-text-color: black;
--md-table-border-color: var(--color-gray-2); --bg-color: var(--color-gray-9);
--bg-color-raised: var(--color-gray-8);
--button-content-color-link: black;
--md-table-header-bg-color: var(--color-gray-8);
--md-table-border-color: var(--color-gray-8);
--bg-color: var(--color-gray-8);
--code-panel-bg-color: var(--color-blue-7);
--layer-color-hover: var(--color-gray-9);
--code-block-text-color: var(--color-gray-1);
--code-block-tokens-comment-color: var(--color-gray-4);
--code-block-tokens-constant-color: var(--color-gray-1);
--code-block-tokens-function-color: var(--color-red-4);
--code-block-tokens-keyword-color: var(--color-magenta-5);
--code-block-tokens-operator-color: black;
--code-block-tokens-string-color: var(--color-green-3);
--bg-raised-gradient: "";
--text-color-helper: var(--color-gray-4);
--button-color-hover: black;
--admonition-success-bg-color: var(--color-green-9);
--admonition-info-bg-color: var(--color-blue-9);
--admonition-warning-bg-color: var(--color-yellow-9);
--admonition-danger-bg-color: var(--color-red-9);
} }
:root.dark { :root.dark {
--link-color-primary: #fff; --link-color-primary: white;
--link-color-visited: #fff; --link-color-visited: white;
--link-color-primary-hover: #9a52ff; --link-color-primary-hover: var(--color-purple-7);
--search-highlight-text-color: #4BB7FF; /* color-blue-4 */ --navbar-bg-color: var(--color-gray-2); /* controls search box bg */
--modal-bg-color: var(--color-gray-2); /* controls search modal bg */
--code-block-tokens-comment-color: #C1C1C2; /* color-gray-3 */ --search-highlight-text-color: var(--color-blue-7);
--code-block-text-color: var(--color-gray-9);
--code-block-tokens-comment-color: var(--color-gray-7);
--code-block-tokens-constant-color: var(--color-gray-9);
--code-block-tokens-keyword-color: var(--color-magenta-8);
--code-block-tokens-string-color: var(--color-blue-8);
--code-panel-bg-color: var(--color-blue-3);
--layer-color-hover: var(--color-gray-3);
--bg-raised-gradient: "";
} }
:root .form-control-plaintext { :root .form-control-plaintext {
color: var(--text-color); color: var(--text-color);
} }
/* Fix unnecessary horizontal scrolling of tables in Japanese */
[lang="ja"] table.md {
word-break: break-word;
}
[lang="ja"] table.md th {
min-width: 7em;
}
[data-component-name="Search/SearchTrigger"] > div { [data-component-name="Search/SearchTrigger"] > div {
justify-content: start; justify-content: start;
width: 100%; width: 100%;

View File

@@ -0,0 +1,4 @@
# Batch
Code samples showing how to create and submit a [Batch transaction](../../docs/concepts/transactions/batch-transactions.md).
Both for simple and multi account batch transactions.

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,198 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/rpc/types"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
var (
CreatePaymentTx = func(sender, receiver *wallet.Wallet, amount txnTypes.CurrencyAmount) *transaction.Payment {
return &transaction.Payment{
BaseTx: transaction.BaseTx{
Account: sender.GetAddress(),
TransactionType: transaction.PaymentTx,
Flags: txnTypes.TfInnerBatchTxn,
},
Amount: amount,
Destination: receiver.GetAddress(),
}
}
)
func main() {
// Configure the client
cfg, err := rpc.NewClientConfig(
"https://s.devnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
// Create and fund wallets
userWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
user2Wallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
receiverWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("Funding wallets...")
if err := client.FundWallet(&userWallet); err != nil {
panic(err)
}
if err := client.FundWallet(&user2Wallet); err != nil {
panic(err)
}
fmt.Println("Wallets funded")
// Check initial balances
userBalance, err := client.GetXrpBalance(userWallet.ClassicAddress)
if err != nil {
userBalance = "0"
}
user2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress)
if err != nil {
user2Balance = "0"
}
receiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress)
if err != nil {
receiverBalance = "0"
}
fmt.Printf("User initial balance: %s XRP\n", userBalance)
fmt.Printf("User2 initial balance: %s XRP\n", user2Balance)
fmt.Printf("Receiver initial balance: %s XRP\n", receiverBalance)
fmt.Println()
fmt.Printf("Batch transaction test\n")
// Create test batch transaction
batchTx := &transaction.Batch{
BaseTx: transaction.BaseTx{
Account: txnTypes.Address(userWallet.ClassicAddress),
TransactionType: transaction.BatchTx,
},
RawTransactions: []txnTypes.RawTransaction{
{RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
{RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
},
}
batchTx.SetAllOrNothingFlag()
flattenedBatchTx := batchTx.Flatten()
fmt.Println("Autofilling flattened batch transaction...")
if err := client.Autofill(&flattenedBatchTx); err != nil {
panic(err)
}
fmt.Println("Signing batch transaction...")
response, err := client.SubmitTxAndWait(flattenedBatchTx, &types.SubmitOptions{
Autofill: false,
Wallet: &userWallet,
})
if err != nil {
panic(err)
}
fmt.Println("Batch transaction submitted")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Printf("Validated: %t\n", response.Validated)
fmt.Println()
// Check final balances
finalUserBalance, err := client.GetXrpBalance(userWallet.ClassicAddress)
if err != nil {
finalUserBalance = "0"
}
finalReceiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress)
if err != nil {
finalReceiverBalance = "0"
}
fmt.Printf("User final balance: %s XRP\n", finalUserBalance)
fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance)
fmt.Println()
fmt.Printf("Multisig Batch transaction test\n")
// Create test batch transaction
multiBatchTx := &transaction.Batch{
BaseTx: transaction.BaseTx{
Account: txnTypes.Address(userWallet.ClassicAddress),
TransactionType: transaction.BatchTx,
},
RawTransactions: []txnTypes.RawTransaction{
{RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
{RawTransaction: CreatePaymentTx(&user2Wallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
},
BatchSigners: []txnTypes.BatchSigner{
{
BatchSigner: txnTypes.BatchSignerData{
Account: txnTypes.Address(user2Wallet.ClassicAddress),
SigningPubKey: user2Wallet.PublicKey,
},
},
},
}
multiBatchTx.SetAllOrNothingFlag()
flattenedMultiBatchTx := multiBatchTx.Flatten()
fmt.Println("Autofilling flattened multi batch transaction...")
if err := client.AutofillMultisigned(&flattenedMultiBatchTx, 1); err != nil {
panic(err)
}
fmt.Println("Signing multi batch transaction...")
if err := wallet.SignMultiBatch(user2Wallet, &flattenedMultiBatchTx, nil); err != nil {
panic(err)
}
response, err = client.SubmitTxAndWait(flattenedMultiBatchTx, &types.SubmitOptions{
Autofill: false,
Wallet: &userWallet,
})
if err != nil {
panic(err)
}
fmt.Println("Multisig Batch transaction submitted")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Printf("Validated: %t\n", response.Validated)
fmt.Println()
// Check final balances
finalUser2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress)
if err != nil {
finalUser2Balance = "0"
}
finalUserBalance, err = client.GetXrpBalance(userWallet.ClassicAddress)
if err != nil {
finalUserBalance = "0"
}
finalReceiverBalance, err = client.GetXrpBalance(receiverWallet.ClassicAddress)
if err != nil {
finalReceiverBalance = "0"
}
fmt.Printf("User final balance: %s XRP\n", finalUserBalance)
fmt.Printf("User2 final balance: %s XRP\n", finalUser2Balance)
fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance)
}

View File

@@ -0,0 +1,199 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
"github.com/Peersyst/xrpl-go/xrpl/websocket/types"
)
var (
CreatePaymentTx = func(sender, receiver *wallet.Wallet, amount txnTypes.CurrencyAmount) *transaction.Payment {
return &transaction.Payment{
BaseTx: transaction.BaseTx{
Account: sender.GetAddress(),
TransactionType: transaction.PaymentTx,
Flags: txnTypes.TfInnerBatchTxn,
},
Amount: amount,
Destination: receiver.GetAddress(),
}
}
)
func main() {
// Connect to testnet
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
// Create and fund wallets
userWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
user2Wallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
receiverWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("Funding wallets...")
if err := client.FundWallet(&userWallet); err != nil {
panic(err)
}
if err := client.FundWallet(&user2Wallet); err != nil {
panic(err)
}
fmt.Println("Wallets funded")
// Check initial balances
userBalance, err := client.GetXrpBalance(userWallet.ClassicAddress)
if err != nil {
userBalance = "0"
}
user2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress)
if err != nil {
user2Balance = "0"
}
receiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress)
if err != nil {
receiverBalance = "0"
}
fmt.Printf("User initial balance: %s XRP\n", userBalance)
fmt.Printf("User2 initial balance: %s XRP\n", user2Balance)
fmt.Printf("Receiver initial balance: %s XRP\n", receiverBalance)
fmt.Println()
fmt.Printf("Batch transaction test\n")
// Create test batch transaction
batchTx := &transaction.Batch{
BaseTx: transaction.BaseTx{
Account: txnTypes.Address(userWallet.ClassicAddress),
TransactionType: transaction.BatchTx,
},
RawTransactions: []txnTypes.RawTransaction{
{RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
{RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
},
}
batchTx.SetAllOrNothingFlag()
flattenedBatchTx := batchTx.Flatten()
fmt.Println("Autofilling flattened batch transaction...")
if err := client.Autofill(&flattenedBatchTx); err != nil {
panic(err)
}
fmt.Println("Signing batch transaction...")
response, err := client.SubmitTxAndWait(flattenedBatchTx, &types.SubmitOptions{
Autofill: false,
Wallet: &userWallet,
})
if err != nil {
panic(err)
}
fmt.Println("Batch transaction submitted")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Printf("Validated: %t\n", response.Validated)
fmt.Println()
// Check final balances
finalUserBalance, err := client.GetXrpBalance(userWallet.ClassicAddress)
if err != nil {
finalUserBalance = "0"
}
finalReceiverBalance, err := client.GetXrpBalance(receiverWallet.ClassicAddress)
if err != nil {
finalReceiverBalance = "0"
}
fmt.Printf("User final balance: %s XRP\n", finalUserBalance)
fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance)
fmt.Println()
fmt.Printf("Multisig Batch transaction test\n")
// Create test batch transaction
multiBatchTx := &transaction.Batch{
BaseTx: transaction.BaseTx{
Account: txnTypes.Address(userWallet.ClassicAddress),
TransactionType: transaction.BatchTx,
},
RawTransactions: []txnTypes.RawTransaction{
{RawTransaction: CreatePaymentTx(&userWallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
{RawTransaction: CreatePaymentTx(&user2Wallet, &receiverWallet, txnTypes.XRPCurrencyAmount(5000000)).Flatten()},
},
BatchSigners: []txnTypes.BatchSigner{
{
BatchSigner: txnTypes.BatchSignerData{
Account: txnTypes.Address(user2Wallet.ClassicAddress),
SigningPubKey: user2Wallet.PublicKey,
},
},
},
}
multiBatchTx.SetAllOrNothingFlag()
flattenedMultiBatchTx := multiBatchTx.Flatten()
fmt.Println("Autofilling flattened multi batch transaction...")
if err := client.AutofillMultisigned(&flattenedMultiBatchTx, 1); err != nil {
panic(err)
}
fmt.Println("Signing multi batch transaction...")
if err := wallet.SignMultiBatch(user2Wallet, &flattenedMultiBatchTx, nil); err != nil {
panic(err)
}
response, err = client.SubmitTxAndWait(flattenedMultiBatchTx, &types.SubmitOptions{
Autofill: false,
Wallet: &userWallet,
})
if err != nil {
panic(err)
}
fmt.Println("Multisig Batch transaction submitted")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Printf("Validated: %t\n", response.Validated)
fmt.Println()
// Check final balances
finalUser2Balance, err := client.GetXrpBalance(user2Wallet.ClassicAddress)
if err != nil {
finalUser2Balance = "0"
}
finalUserBalance, err = client.GetXrpBalance(userWallet.ClassicAddress)
if err != nil {
finalUserBalance = "0"
}
finalReceiverBalance, err = client.GetXrpBalance(receiverWallet.ClassicAddress)
if err != nil {
finalReceiverBalance = "0"
}
fmt.Printf("User final balance: %s XRP\n", finalUserBalance)
fmt.Printf("User2 final balance: %s XRP\n", finalUser2Balance)
fmt.Printf("Receiver final balance: %s XRP\n", finalReceiverBalance)
}

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,152 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
cfg, err := rpc.NewClientConfig(
"https://s.altnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
w, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
receiverWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("Setting up wallets...")
if err := client.FundWallet(&w); err != nil {
panic(err)
}
fmt.Println("Sender wallet funded!")
if err := client.FundWallet(&receiverWallet); err != nil {
panic(err)
}
fmt.Println("Receiver wallet funded!")
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println("Sender wallet:", w.ClassicAddress)
fmt.Println("Receiver wallet:", receiverWallet.ClassicAddress)
fmt.Println()
fmt.Println("Creating check...")
cc := &transaction.CheckCreate{
BaseTx: transaction.BaseTx{
Account: w.GetAddress(),
},
Destination: receiverWallet.GetAddress(),
SendMax: types.XRPCurrencyAmount(1000000),
InvoiceID: "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291",
}
flatCc := cc.Flatten()
if err := client.Autofill(&flatCc); err != nil {
panic(err)
}
blob, _, err := w.Sign(flatCc)
if err != nil {
panic(err)
}
res, err := client.SubmitTxBlobAndWait(blob, false)
if err != nil {
panic(err)
}
if !res.Validated {
fmt.Println("Check creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Check created!")
fmt.Printf("Hash: %s\n", res.Hash.String())
fmt.Println()
meta, ok := res.Meta.(map[string]interface{})
if !ok {
fmt.Println("Meta is not of type TxObjMeta")
return
}
var checkID string
affectedNodes := meta["AffectedNodes"].([]interface{})
for _, node := range affectedNodes {
affectedNode, ok := node.(map[string]interface{})
if !ok {
fmt.Println("Node is not of type map[string]interface{}")
return
}
createdNode, ok := affectedNode["CreatedNode"].(map[string]interface{})
if !ok {
continue
}
if createdNode["LedgerEntryType"] == string(ledger.CheckEntry) {
checkID = createdNode["LedgerIndex"].(string)
}
}
if checkID == "" {
fmt.Println("Check not found")
return
}
fmt.Println("Cashing out check...")
checkCash := &transaction.CheckCash{
BaseTx: transaction.BaseTx{
Account: receiverWallet.GetAddress(),
},
CheckID: types.Hash256(checkID),
Amount: types.XRPCurrencyAmount(1000000),
}
flatCheckCash := checkCash.Flatten()
if err := client.Autofill(&flatCheckCash); err != nil {
panic(err)
}
blob, _, err = receiverWallet.Sign(flatCheckCash)
if err != nil {
panic(err)
}
res, err = client.SubmitTxBlobAndWait(blob, false)
if err != nil {
panic(err)
}
fmt.Println("Check cashed out!")
fmt.Printf("Hash: %s\n", res.Hash.String())
fmt.Println()
}

View File

@@ -0,0 +1,163 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
func main() {
fmt.Println("Connecting to testnet...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.altnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
if !client.IsConnected() {
fmt.Println("Failed to connect to testnet")
return
}
fmt.Println("Connected to testnet")
fmt.Println()
w, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
receiverWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("Setting up wallets...")
if err := client.FundWallet(&w); err != nil {
panic(err)
}
fmt.Println("Sender wallet funded!")
if err := client.FundWallet(&receiverWallet); err != nil {
panic(err)
}
fmt.Println("Receiver wallet funded!")
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println("Sender wallet:", w.ClassicAddress)
fmt.Println("Receiver wallet:", receiverWallet.ClassicAddress)
fmt.Println()
fmt.Println("Creating check...")
cc := &transaction.CheckCreate{
BaseTx: transaction.BaseTx{
Account: w.GetAddress(),
},
Destination: receiverWallet.GetAddress(),
SendMax: types.XRPCurrencyAmount(1000000),
InvoiceID: "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291",
}
flatCc := cc.Flatten()
if err := client.Autofill(&flatCc); err != nil {
panic(err)
}
blob, _, err := w.Sign(flatCc)
if err != nil {
panic(err)
}
res, err := client.SubmitTxBlobAndWait(blob, false)
if err != nil {
panic(err)
}
if !res.Validated {
fmt.Println("Check creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Check created!")
fmt.Printf("Hash: %s\n", res.Hash.String())
fmt.Println()
meta, ok := res.Meta.(map[string]interface{})
if !ok {
fmt.Println("Meta is not of type TxObjMeta")
return
}
var checkID string
affectedNodes := meta["AffectedNodes"].([]interface{})
for _, node := range affectedNodes {
affectedNode, ok := node.(map[string]interface{})
if !ok {
fmt.Println("Node is not of type map[string]interface{}")
return
}
createdNode, ok := affectedNode["CreatedNode"].(map[string]interface{})
if !ok {
continue
}
if createdNode["LedgerEntryType"] == string(ledger.CheckEntry) {
checkID = createdNode["LedgerIndex"].(string)
}
}
if checkID == "" {
fmt.Println("Check not found")
return
}
fmt.Println("Cashing out check...")
checkCash := &transaction.CheckCash{
BaseTx: transaction.BaseTx{
Account: receiverWallet.GetAddress(),
},
CheckID: types.Hash256(checkID),
Amount: types.XRPCurrencyAmount(1000000),
}
flatCheckCash := checkCash.Flatten()
if err := client.Autofill(&flatCheckCash); err != nil {
panic(err)
}
blob, _, err = receiverWallet.Sign(flatCheckCash)
if err != nil {
panic(err)
}
res, err = client.SubmitTxBlobAndWait(blob, false)
if err != nil {
panic(err)
}
fmt.Println("Check cashed out!")
fmt.Printf("Hash: %s\n", res.Hash.String())
fmt.Println()
}

View File

@@ -0,0 +1,3 @@
# Clawback
Create, configure, and execute a Clawback transaction to reclaim issued tokens from a trust line on the XRPL.

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,235 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
const (
currencyCode = "FOO"
)
func main() {
//
// Configure client
//
cfg, err := rpc.NewClientConfig(
"https://s.altnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
//
// Configure wallets
//
fmt.Println("Setting up wallets...")
coldWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&coldWallet)
if err != nil {
panic(err)
}
fmt.Println("Cold wallet funded!")
hotWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&hotWallet)
if err != nil {
panic(err)
}
fmt.Println("Hot wallet funded!")
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println("Cold wallet:", coldWallet.ClassicAddress)
fmt.Println("Hot wallet:", hotWallet.ClassicAddress)
fmt.Println()
//
// Configure cold address settings
//
fmt.Println("Configuring cold address settings...")
coldWalletAccountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
TickSize: types.TickSize(5),
TransferRate: types.TransferRate(0),
Domain: types.Domain("6578616D706C652E636F6D"), // example.com
}
coldWalletAccountSet.SetAsfAllowTrustLineClawback()
coldWalletAccountSet.SetDisallowXRP()
coldWalletAccountSet.SetRequireDestTag()
flattenedTx := coldWalletAccountSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err := coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err := client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold wallet unfreezing failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Cold address settings configured!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Create trust line from hot to cold address
//
fmt.Println("Creating trust line from hot to cold address...")
hotColdTrustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100000000000000",
},
}
flattenedTx = hotColdTrustSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Trust line from hot to cold address creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Trust line from hot to cold address created!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Send tokens from cold wallet to hot wallet
//
fmt.Println("Sending tokens from cold wallet to hot wallet...")
coldToHotPayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "3800",
},
Destination: types.Address(hotWallet.ClassicAddress),
DestinationTag: types.DestinationTag(1),
}
flattenedTx = coldToHotPayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from cold wallet to hot wallet!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Tokens sent from cold wallet to hot wallet!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Claw back tokens from customer one
//
fmt.Println("Clawing back tokens from hot wallet...")
coldWalletClawback := &transactions.Clawback{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(hotWallet.ClassicAddress),
Value: "50",
},
}
flattenedTx = coldWalletClawback.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not clawed back from customer one!")
fmt.Println("Try again!")
return
}
fmt.Println("Tokens clawed back from customer one!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
}

View File

@@ -0,0 +1,241 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
const (
currencyCode = "FOO"
)
func main() {
//
// Configure client
//
fmt.Println("Setting up client...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.altnet.rippletest.net").
WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
fmt.Println("Client configured!")
fmt.Println()
fmt.Println("Connecting to server...")
if err := client.Connect(); err != nil {
panic(err)
}
fmt.Println("Connection: ", client.IsConnected())
//
// Configure wallets
//
fmt.Println("Setting up wallets...")
coldWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&coldWallet)
if err != nil {
panic(err)
}
fmt.Println("Cold wallet funded!")
hotWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&hotWallet)
if err != nil {
panic(err)
}
fmt.Println("Hot wallet funded!")
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println("Cold wallet:", coldWallet.ClassicAddress)
fmt.Println("Hot wallet:", hotWallet.ClassicAddress)
fmt.Println()
//
// Configure cold address settings
//
fmt.Println("Configuring cold address settings...")
coldWalletAccountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
TickSize: types.TickSize(5),
TransferRate: types.TransferRate(0),
Domain: types.Domain("6578616D706C652E636F6D"), // example.com
}
coldWalletAccountSet.SetAsfAllowTrustLineClawback()
coldWalletAccountSet.SetDisallowXRP()
coldWalletAccountSet.SetRequireDestTag()
flattenedTx := coldWalletAccountSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err := coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err := client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold wallet unfreezing failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Cold address settings configured!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Create trust line from hot to cold address
//
fmt.Println("Creating trust line from hot to cold address...")
hotColdTrustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100000000000000",
},
}
flattenedTx = hotColdTrustSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Trust line from hot to cold address creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Trust line from hot to cold address created!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Send tokens from cold wallet to hot wallet
//
fmt.Println("Sending tokens from cold wallet to hot wallet...")
coldToHotPayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "3800",
},
Destination: types.Address(hotWallet.ClassicAddress),
DestinationTag: types.DestinationTag(1),
}
flattenedTx = coldToHotPayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from cold wallet to hot wallet!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Tokens sent from cold wallet to hot wallet!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Claw back tokens from customer one
//
fmt.Println("Clawing back tokens from hot wallet...")
coldWalletClawback := &transactions.Clawback{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(hotWallet.ClassicAddress),
Value: "50",
},
}
flattenedTx = coldWalletClawback.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not clawed back from customer one!")
fmt.Println("Try again!")
return
}
fmt.Println("Tokens clawed back from customer one!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
}

View File

@@ -0,0 +1,3 @@
# Credential
Create, accept, and delete a credential on the XRPL using dedicated transactions between issuer and subject wallets.

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,104 @@
package main
import (
"encoding/hex"
"fmt"
"time"
"github.com/Peersyst/xrpl-go/examples/clients"
"github.com/Peersyst/xrpl-go/pkg/crypto"
rippleTime "github.com/Peersyst/xrpl-go/xrpl/time"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
// As of February 2025, Credential is only available on Devnet.
client := clients.GetDevnetRpcClient()
// Configure wallets
// Issuer
fmt.Println("Setting up credential issuer wallet...")
issuer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&issuer)
if err != nil {
panic(err)
}
fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress)
// -----------------------------------------------------
// Subject (destination)
fmt.Println("Setting up Subject wallet...")
subjectWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&subjectWallet)
if err != nil {
panic(err)
}
fmt.Printf("Subject wallet funded: %s\n", subjectWallet.ClassicAddress)
// -----------------------------------------------------
// Creating the CredentialCreate transaction
fmt.Println("Creating CredentialCreate transaction...")
expiration, err := rippleTime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339))
credentialType := types.CredentialType("6D795F63726564656E7469616C")
if err != nil {
panic(err)
}
txn := &transaction.CredentialCreate{
BaseTx: transaction.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
CredentialType: credentialType,
Subject: types.Address(subjectWallet.ClassicAddress),
Expiration: uint32(expiration),
URI: hex.EncodeToString([]byte("https://example.com")),
}
clients.SubmitTxBlobAndWait(client, txn, issuer)
// -----------------------------------------------------
// Creating the CredentialAccept transaction
fmt.Println("Creating CredentialAccept transaction...")
acceptTxn := &transaction.CredentialAccept{
BaseTx: transaction.BaseTx{
Account: types.Address(subjectWallet.ClassicAddress),
},
CredentialType: credentialType,
Issuer: types.Address(issuer.ClassicAddress),
}
clients.SubmitTxBlobAndWait(client, acceptTxn, subjectWallet)
// -----------------------------------------------------
// Creating the CredentialDelete transaction
fmt.Println("Creating CredentialDelete transaction...")
deleteTxn := &transaction.CredentialDelete{
BaseTx: transaction.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
CredentialType: credentialType,
Issuer: types.Address(issuer.ClassicAddress),
Subject: types.Address(subjectWallet.ClassicAddress),
}
clients.SubmitTxBlobAndWait(client, deleteTxn, issuer)
}

View File

@@ -0,0 +1,116 @@
package main
import (
"encoding/hex"
"fmt"
"time"
"github.com/Peersyst/xrpl-go/examples/clients"
"github.com/Peersyst/xrpl-go/pkg/crypto"
rippleTime "github.com/Peersyst/xrpl-go/xrpl/time"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
fmt.Println("Setting up client...")
client := clients.GetDevnetWebsocketClient()
fmt.Println("Connecting to server...")
if err := client.Connect(); err != nil {
panic(err)
}
fmt.Println("Client configured!")
fmt.Println()
fmt.Printf("Connection: %t", client.IsConnected())
fmt.Println()
// Configure wallets
// Issuer
fmt.Println("Setting up credential issuer wallet...")
issuer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&issuer)
if err != nil {
panic(err)
}
fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress)
// -----------------------------------------------------
// Subject (destination)
fmt.Println("Setting up Subject wallet...")
subjectWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&subjectWallet)
if err != nil {
panic(err)
}
fmt.Printf("Subject wallet funded: %s\n", subjectWallet.ClassicAddress)
// -----------------------------------------------------
// Creating the CredentialCreate transaction
fmt.Println("Creating CredentialCreate transaction...")
expiration, err := rippleTime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339))
credentialType := types.CredentialType("6D795F63726564656E7469616C")
if err != nil {
panic(err)
}
txn := &transaction.CredentialCreate{
BaseTx: transaction.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
CredentialType: credentialType,
Subject: types.Address(subjectWallet.ClassicAddress),
Expiration: uint32(expiration),
URI: hex.EncodeToString([]byte("https://example.com")),
}
clients.SubmitTxBlobAndWait(client, txn, issuer)
// -----------------------------------------------------
// Creating the CredentialAccept transaction
fmt.Println("Creating CredentialAccept transaction...")
acceptTxn := &transaction.CredentialAccept{
BaseTx: transaction.BaseTx{
Account: types.Address(subjectWallet.ClassicAddress),
},
CredentialType: credentialType,
Issuer: types.Address(issuer.ClassicAddress),
}
clients.SubmitTxBlobAndWait(client, acceptTxn, subjectWallet)
// -----------------------------------------------------
// Creating the CredentialDelete transaction
fmt.Println("Creating CredentialDelete transaction...")
deleteTxn := &transaction.CredentialDelete{
BaseTx: transaction.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
CredentialType: credentialType,
Issuer: types.Address(issuer.ClassicAddress),
Subject: types.Address(subjectWallet.ClassicAddress),
}
clients.SubmitTxBlobAndWait(client, deleteTxn, issuer)
}

View File

@@ -0,0 +1,3 @@
# Delegate
Example delegating payment permission to an account and executing on behalf the delegator.

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,125 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/rpc/types"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
// Configure the client
cfg, err := rpc.NewClientConfig(
"https://s.devnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
// Create and fund wallets
delegatorWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
delegateeWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("Funding wallets...")
if err := client.FundWallet(&delegatorWallet); err != nil {
panic(err)
}
if err := client.FundWallet(&delegateeWallet); err != nil {
panic(err)
}
fmt.Println("Wallets funded")
// Check initial balances
delegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress)
if err != nil {
delegatorBalance = "0"
}
delegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress)
if err != nil {
delegateeBalance = "0"
}
fmt.Printf("Delegator initial balance: %s XRP\n", delegatorBalance)
fmt.Printf("Delegatee initial balance: %s XRP\n", delegateeBalance)
fmt.Println()
// Create DelegateSet transaction
delegateSetTx := &transactions.DelegateSet{
BaseTx: transactions.BaseTx{
Account: txnTypes.Address(delegatorWallet.ClassicAddress),
},
Authorize: txnTypes.Address(delegateeWallet.ClassicAddress),
Permissions: []txnTypes.Permission{
{
Permission: txnTypes.PermissionValue{
PermissionValue: "Payment",
},
},
},
}
// Submit DelegateSet transaction
response, err := client.SubmitTxAndWait(delegateSetTx.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &delegatorWallet,
})
if err != nil {
panic(err)
}
fmt.Println("DelegateSet transaction submitted")
fmt.Printf("Hash: %s\n", response.Hash)
fmt.Printf("Validated: %t\n", response.Validated)
fmt.Println()
// Create delegated payment transaction
delegatedPaymentTx := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: txnTypes.Address(delegatorWallet.ClassicAddress),
Delegate: txnTypes.Address(delegateeWallet.ClassicAddress),
},
Destination: txnTypes.Address(delegateeWallet.ClassicAddress),
Amount: txnTypes.XRPCurrencyAmount(1000000), // 1 XRP
}
// Submit delegated payment
response2, err := client.SubmitTxAndWait(delegatedPaymentTx.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &delegateeWallet,
})
if err != nil {
panic(err)
}
fmt.Println("Delegated payment submitted")
fmt.Printf("Hash: %s\n", response2.Hash)
fmt.Printf("Validated: %t\n", response2.Validated)
fmt.Println()
// Check final balances
finalDelegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress)
if err != nil {
finalDelegatorBalance = "0"
}
finalDelegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress)
if err != nil {
finalDelegateeBalance = "0"
}
fmt.Printf("Delegator final balance: %s XRP\n", finalDelegatorBalance)
fmt.Printf("Delegatee final balance: %s XRP\n", finalDelegateeBalance)
}

View File

@@ -0,0 +1,140 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
func main() {
// Connect to testnet
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
// Create and fund wallets
delegatorWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
delegateeWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("Funding wallets...")
if err := client.FundWallet(&delegatorWallet); err != nil {
panic(err)
}
if err := client.FundWallet(&delegateeWallet); err != nil {
panic(err)
}
fmt.Println("Wallets funded")
// Check initial balances
delegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress)
if err != nil {
delegatorBalance = "0"
}
delegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress)
if err != nil {
delegateeBalance = "0"
}
fmt.Printf("Delegator initial balance: %s XRP\n", delegatorBalance)
fmt.Printf("Delegatee initial balance: %s XRP\n", delegateeBalance)
fmt.Println()
// Create DelegateSet transaction
delegateSetTx := &transactions.DelegateSet{
BaseTx: transactions.BaseTx{
Account: types.Address(delegatorWallet.ClassicAddress),
},
Authorize: types.Address(delegateeWallet.ClassicAddress),
Permissions: []types.Permission{
{
Permission: types.PermissionValue{
PermissionValue: "Payment",
},
},
},
}
// Submit DelegateSet transaction
flattenedTx := delegateSetTx.Flatten()
if err := client.Autofill(&flattenedTx); err != nil {
panic(err)
}
txBlob, _, err := delegatorWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err := client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
fmt.Println("DelegateSet transaction submitted")
fmt.Printf("Hash: %s\n", response.Hash)
fmt.Printf("Validated: %t\n", response.Validated)
fmt.Println()
// Create delegated payment transaction
delegatedPaymentTx := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(delegatorWallet.ClassicAddress),
Delegate: types.Address(delegateeWallet.ClassicAddress),
},
Destination: types.Address(delegateeWallet.ClassicAddress),
Amount: types.XRPCurrencyAmount(1000000), // 1 XRP
}
// Submit delegated payment
flatDelegatedPayment := delegatedPaymentTx.Flatten()
if err := client.Autofill(&flatDelegatedPayment); err != nil {
panic(err)
}
txBlob2, _, err := delegateeWallet.Sign(flatDelegatedPayment)
if err != nil {
panic(err)
}
response2, err := client.SubmitTxBlobAndWait(txBlob2, false)
if err != nil {
panic(err)
}
fmt.Println("Delegated payment submitted")
fmt.Printf("Hash: %s\n", response2.Hash)
fmt.Printf("Validated: %t\n", response2.Validated)
fmt.Println()
// Check final balances
finalDelegatorBalance, err := client.GetXrpBalance(delegatorWallet.ClassicAddress)
if err != nil {
finalDelegatorBalance = "0"
}
finalDelegateeBalance, err := client.GetXrpBalance(delegateeWallet.ClassicAddress)
if err != nil {
finalDelegateeBalance = "0"
}
fmt.Printf("Delegator final balance: %s XRP\n", finalDelegatorBalance)
fmt.Printf("Delegatee final balance: %s XRP\n", finalDelegateeBalance)
}

View File

@@ -0,0 +1,3 @@
# DepositPreauth
Example of DepositPreauth transaction demonstrating how deposit permissions can be managed.

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,214 @@
package main
import (
"encoding/hex"
"fmt"
"time"
"github.com/Peersyst/xrpl-go/examples/clients"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/queries/account"
"github.com/Peersyst/xrpl-go/xrpl/queries/common"
rippletime "github.com/Peersyst/xrpl-go/xrpl/time"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
client := clients.GetDevnetRpcClient()
// Configure wallets
// Issuer
fmt.Println("Setting up credential issuer wallet...")
issuer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&issuer)
if err != nil {
panic(err)
}
fmt.Printf("Credential issuer wallet funded: %s\n", issuer.ClassicAddress)
// -----------------------------------------------------
// Holder 1
fmt.Println("Setting up holder 1 wallet...")
holderWallet1, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&holderWallet1)
if err != nil {
panic(err)
}
fmt.Printf("Holder 1 wallet funded: %s\n", holderWallet1.ClassicAddress)
// -----------------------------------------------------
// Enabling DepositAuth on the issuer account with an AccountSet transaction
fmt.Println("Enabling DepositAuth on the issuer account...")
accountSetTx := &transaction.AccountSet{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.AccountSetTx,
},
}
accountSetTx.SetAsfDepositAuth()
clients.SubmitTxBlobAndWait(client, accountSetTx, issuer)
// -----------------------------------------------------
// Creating the CredentialCreate transaction
fmt.Println("Creating the CredentialCreate transaction...")
expiration, err := rippletime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339))
if err != nil {
panic(err)
}
credentialType := types.CredentialType("6D795F63726564656E7469616C") // my_credential
credentialCreateTx := &transaction.CredentialCreate{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.CredentialCreateTx,
},
Expiration: uint32(expiration),
CredentialType: credentialType,
Subject: types.Address(holderWallet1.ClassicAddress),
URI: hex.EncodeToString([]byte("https://example.com")),
}
clients.SubmitTxBlobAndWait(client, credentialCreateTx, issuer)
// -----------------------------------------------------
// Creating the CredentialAccept transaction
fmt.Println("Creating the CredentialAccept transaction...")
credentialAcceptTx := &transaction.CredentialAccept{
BaseTx: transaction.BaseTx{
Account: holderWallet1.ClassicAddress,
TransactionType: transaction.CredentialAcceptTx,
},
CredentialType: credentialType,
Issuer: types.Address(issuer.ClassicAddress),
}
clients.SubmitTxBlobAndWait(client, credentialAcceptTx, holderWallet1)
// -----------------------------------------------------
// Creating the DepositPreauth transaction
fmt.Println("Creating the DepositPreauth transaction using AuthorizeCredentials...")
depositPreauthTx := &transaction.DepositPreauth{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.DepositPreauthTx,
},
AuthorizeCredentials: []types.AuthorizeCredentialsWrapper{
{
Credential: types.AuthorizeCredentials{
Issuer: issuer.ClassicAddress,
CredentialType: credentialType,
},
},
},
}
clients.SubmitTxBlobAndWait(client, depositPreauthTx, issuer)
// -----------------------------------------------------
// Get the credential ID
fmt.Println("Getting the credential ID from the holder 1 account...")
objectsRequest := &account.ObjectsRequest{
Account: holderWallet1.ClassicAddress,
Type: account.CredentialObject,
LedgerIndex: common.Validated,
}
objectsResponse, err := client.GetAccountObjects(objectsRequest)
if err != nil {
panic(err)
}
// Check if we have any credential objects
if len(objectsResponse.AccountObjects) == 0 {
fmt.Println("No credential objects found")
return
}
// Extract the credential ID
credentialID, ok := objectsResponse.AccountObjects[0]["index"].(string)
if !ok {
fmt.Println("Could not extract credential ID from response")
return
}
fmt.Printf("Credential ID: %s\n", credentialID)
fmt.Println()
// -----------------------------------------------------
// Sending XRP to the holder 1 account
fmt.Println("Sending XRP to the issuer account, should succeed...")
sendTx := &transaction.Payment{
BaseTx: transaction.BaseTx{
Account: holderWallet1.ClassicAddress,
TransactionType: transaction.PaymentTx,
},
Amount: types.XRPCurrencyAmount(1000000),
Destination: issuer.ClassicAddress,
CredentialIDs: types.CredentialIDs{credentialID},
}
clients.SubmitTxBlobAndWait(client, sendTx, holderWallet1)
// -----------------------------------------------------
// Unauthorizing the holder 1 account
fmt.Println("Unauthorizing the holder 1 account with the DepositPreauth transaction and the UnauthorizeCredentials field...")
unauthorizeTx := &transaction.DepositPreauth{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.DepositPreauthTx,
},
UnauthorizeCredentials: []types.AuthorizeCredentialsWrapper{
{
Credential: types.AuthorizeCredentials{
Issuer: issuer.ClassicAddress,
CredentialType: credentialType,
},
},
},
}
clients.SubmitTxBlobAndWait(client, unauthorizeTx, issuer)
// -----------------------------------------------------
// Sending XRP to the holder 1 account again (which should fail)
fmt.Println("Sending XRP to the issuer account again (which should fail)...")
sendTx2 := &transaction.Payment{
BaseTx: transaction.BaseTx{
Account: holderWallet1.ClassicAddress,
TransactionType: transaction.PaymentTx,
},
Amount: types.XRPCurrencyAmount(1000000),
Destination: issuer.ClassicAddress,
CredentialIDs: types.CredentialIDs{credentialID},
}
clients.SubmitTxBlobAndWait(client, sendTx2, holderWallet1)
}

View File

@@ -0,0 +1,227 @@
package main
import (
"encoding/hex"
"fmt"
"time"
"github.com/Peersyst/xrpl-go/examples/clients"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/queries/account"
"github.com/Peersyst/xrpl-go/xrpl/queries/common"
rippletime "github.com/Peersyst/xrpl-go/xrpl/time"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
fmt.Println("Setting up client...")
client := clients.GetDevnetWebsocketClient()
fmt.Println("Connecting to server...")
if err := client.Connect(); err != nil {
panic(err)
}
fmt.Println("Client configured!")
fmt.Println()
fmt.Printf("Connection: %t", client.IsConnected())
fmt.Println()
// Configure wallets
// Issuer
fmt.Println("Setting up credential issuer wallet...")
issuer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&issuer)
if err != nil {
panic(err)
}
fmt.Printf("Credential issuer wallet funded: %s\n", issuer.ClassicAddress)
// -----------------------------------------------------
// Holder 1
fmt.Println("Setting up holder 1 wallet...")
holderWallet1, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&holderWallet1)
if err != nil {
panic(err)
}
fmt.Printf("Holder 1 wallet funded: %s\n", holderWallet1.ClassicAddress)
// -----------------------------------------------------
// Enabling DepositAuth on the issuer account with an AccountSet transaction
fmt.Println("Enabling DepositAuth on the issuer account...")
accountSetTx := &transaction.AccountSet{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.AccountSetTx,
},
}
accountSetTx.SetAsfDepositAuth()
clients.SubmitTxBlobAndWait(client, accountSetTx, issuer)
// -----------------------------------------------------
// Creating the CredentialCreate transaction
fmt.Println("Creating the CredentialCreate transaction...")
expiration, err := rippletime.IsoTimeToRippleTime(time.Now().Add(time.Hour * 24).Format(time.RFC3339))
if err != nil {
panic(err)
}
credentialType := types.CredentialType("6D795F63726564656E7469616C") // my_credential
credentialCreateTx := &transaction.CredentialCreate{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.CredentialCreateTx,
},
Expiration: uint32(expiration),
CredentialType: credentialType,
Subject: types.Address(holderWallet1.ClassicAddress),
URI: hex.EncodeToString([]byte("https://example.com")),
}
clients.SubmitTxBlobAndWait(client, credentialCreateTx, issuer)
// -----------------------------------------------------
// Creating the CredentialAccept transaction
fmt.Println("Creating the CredentialAccept transaction...")
credentialAcceptTx := &transaction.CredentialAccept{
BaseTx: transaction.BaseTx{
Account: holderWallet1.ClassicAddress,
TransactionType: transaction.CredentialAcceptTx,
},
CredentialType: credentialType,
Issuer: types.Address(issuer.ClassicAddress),
}
clients.SubmitTxBlobAndWait(client, credentialAcceptTx, holderWallet1)
// -----------------------------------------------------
// Creating the DepositPreauth transaction
fmt.Println("Creating the DepositPreauth transaction using AuthorizeCredentials...")
depositPreauthTx := &transaction.DepositPreauth{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.DepositPreauthTx,
},
AuthorizeCredentials: []types.AuthorizeCredentialsWrapper{
{
Credential: types.AuthorizeCredentials{
Issuer: issuer.ClassicAddress,
CredentialType: credentialType,
},
},
},
}
clients.SubmitTxBlobAndWait(client, depositPreauthTx, issuer)
// -----------------------------------------------------
// Get the credential ID
fmt.Println("Getting the credential ID from the holder 1 account...")
objectsRequest := &account.ObjectsRequest{
Account: holderWallet1.ClassicAddress,
Type: account.CredentialObject,
LedgerIndex: common.Validated,
}
objectsResponse, err := client.GetAccountObjects(objectsRequest)
if err != nil {
panic(err)
}
// Check if we have any credential objects
if len(objectsResponse.AccountObjects) == 0 {
fmt.Println("No credential objects found")
return
}
// Extract the credential ID
credentialID, ok := objectsResponse.AccountObjects[0]["index"].(string)
if !ok {
fmt.Println("Could not extract credential ID from response")
return
}
fmt.Printf("Credential ID: %s\n", credentialID)
fmt.Println()
// -----------------------------------------------------
// Sending XRP to the holder 1 account
fmt.Println("Sending XRP to the issuer account, should succeed...")
sendTx := &transaction.Payment{
BaseTx: transaction.BaseTx{
Account: holderWallet1.ClassicAddress,
TransactionType: transaction.PaymentTx,
},
Amount: types.XRPCurrencyAmount(1000000),
Destination: issuer.ClassicAddress,
CredentialIDs: types.CredentialIDs{credentialID},
}
clients.SubmitTxBlobAndWait(client, sendTx, holderWallet1)
// -----------------------------------------------------
// Unauthorize the holder 1 account
fmt.Println("Unauthorize the holder 1 account with the DepositPreauth transaction and the UnauthorizeCredentials field...")
unauthorizeTx := &transaction.DepositPreauth{
BaseTx: transaction.BaseTx{
Account: issuer.ClassicAddress,
TransactionType: transaction.DepositPreauthTx,
},
UnauthorizeCredentials: []types.AuthorizeCredentialsWrapper{
{
Credential: types.AuthorizeCredentials{
Issuer: issuer.ClassicAddress,
CredentialType: credentialType,
},
},
},
}
clients.SubmitTxBlobAndWait(client, unauthorizeTx, issuer)
// -----------------------------------------------------
// Sending XRP to the holder 1 account again (which should fail)
fmt.Println("Sending XRP to the issuer account again (which should fail)...")
sendTx2 := &transaction.Payment{
BaseTx: transaction.BaseTx{
Account: holderWallet1.ClassicAddress,
TransactionType: transaction.PaymentTx,
},
Amount: types.XRPCurrencyAmount(1000000),
Destination: issuer.ClassicAddress,
CredentialIDs: types.CredentialIDs{credentialID},
}
clients.SubmitTxBlobAndWait(client, sendTx2, holderWallet1)
}

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,335 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/currency"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
const (
currencyCode = "USDA"
)
type SubmittableTransaction interface {
TxType() transactions.TxType
Flatten() transactions.FlatTransaction // Ensures all transactions can be flattened
}
func main() {
client := getRpcClient()
// Configure wallets
// Issuer
fmt.Println("Setting up issuer wallet...")
issuer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&issuer)
if err != nil {
panic(err)
}
fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress)
// -----------------------------------------------------
// Holder 1
fmt.Println("Setting up holder 1 wallet...")
holderWallet1, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&holderWallet1)
if err != nil {
panic(err)
}
fmt.Printf("Holder wallet 1 funded: %s\n", holderWallet1.ClassicAddress)
// -----------------------------------------------------
// Holder 2
fmt.Println("Setting up holder 2 wallet...")
holderWallet2, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&holderWallet2)
if err != nil {
panic(err)
}
fmt.Printf("Holder wallet 2 funded: %s\n", holderWallet2.ClassicAddress)
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println()
// -----------------------------------------------------
// Configuring Issuing account
fmt.Println("Configuring issuer address settings...")
accountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
Domain: types.Domain("697373756572"), // issuer
}
accountSet.SetAsfDefaultRipple()
submitAndWait(client, accountSet, issuer)
// -----------------------------------------------------
// Trustline from the holder 1 to the issuer
fmt.Println("Setting up trustline from holder 1 to the issuer...")
trustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "1000000000",
}}
trustSet.SetSetNoRippleFlag()
submitAndWait(client, trustSet, holderWallet1)
// -----------------------------------------------------
// Trustline from the holder 2 to the issuer
fmt.Println("Setting up trustline from holder 2 to the issuer...")
trustSet = &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet2.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "1000000000",
},
}
trustSet.SetSetNoRippleFlag()
submitAndWait(client, trustSet, holderWallet2)
// -----------------------------------------------------
// Minting to Holder 1
fmt.Println("Minting to Holder 1...")
payment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
Destination: types.Address(holderWallet1.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "50000",
},
}
submitAndWait(client, payment, issuer)
// -----------------------------------------------------
// Minting to Holder 2
fmt.Println("Minting to Holder 2...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "40000",
},
}
submitAndWait(client, payment, issuer)
// -----------------------------------------------------
// Sending payment from Holder 1 to Holder 2
fmt.Println("Sending payment from Holder 1 to Holder 2...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "20",
},
}
submitAndWait(client, payment, holderWallet1)
// -----------------------------------------------------
// Freezing and Deep Freezing holder1
fmt.Println("Freezing and Deep Freezing holder 1 trustline...")
trustSet = &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(holderWallet1.ClassicAddress),
Value: "0",
},
}
trustSet.SetSetFreezeFlag()
trustSet.SetSetDeepFreezeFlag()
submitAndWait(client, trustSet, issuer)
// ------------------- SHOULD FAIL ------------------
// Sending payment from Holder 1 to Holder 2 (which should fail), Holder 1 can't decrease its balance
fmt.Println("Sending payment from Holder 1 to Holder 2 (which should fail). Holder 1 can't decrease its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet1)
// ------------------- SHOULD FAIL ------------------
// Sending payment from Holder 2 to Holder 1 (which should fail), Holder 1 can't increase its balance
fmt.Println("Sending payment from Holder 2 to Holder 1 (which should fail). Holder 1 can't increase its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet2.ClassicAddress),
},
Destination: types.Address(holderWallet1.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet2)
// ------------------- SHOULD FAIL ------------------
// Creating OfferCreate transaction (which should fail), Holder 1 can't create an offer
fmt.Println("Creating OfferCreate transaction (which should fail). Holder 1 can't create an offer...")
offerCreate := &transactions.OfferCreate{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
TakerPays: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
TakerGets: types.XRPCurrencyAmount(10),
}
submitAndWait(client, offerCreate, holderWallet1)
// -----------------------------------------------------
// Unfreezing and Deep Unfreezing holder 1
fmt.Println("Unfreezing and Deep Unfreezing holder 1 trustline...")
trustSet = &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(holderWallet1.ClassicAddress),
Value: "0",
},
}
trustSet.SetClearFreezeFlag()
trustSet.SetClearDeepFreezeFlag()
submitAndWait(client, trustSet, issuer)
// -----------------------------------------------------
// Sending payment from Holder 1 to Holder 2 (which should succeed), Holder 1 can decrease its balance
fmt.Println("Sending payment from Holder 1 to Holder 2 (which should succeed). Holder 1 can decrease its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet1)
// -----------------------------------------------------
// Sending payment from Holder 2 to Holder 1 (which should succeed), Holder 1 can increase its balance
fmt.Println("Sending payment from Holder 2 to Holder 1 (which should succeed). Holder 1 can increase its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet2.ClassicAddress),
},
Destination: types.Address(holderWallet1.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet2)
}
// getRpcClient returns a new rpc client
func getRpcClient() *rpc.Client {
cfg, err := rpc.NewClientConfig(
// DeepFreeze only available on Devnet as of February 2025, change to testnet/mainnet once the amendment passes.
"https://s.devnet.rippletest.net:51234",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}
return rpc.NewClient(cfg)
}
// submitAndWait submits a transaction and waits for it to be included in a validated ledger
func submitAndWait(client *rpc.Client, txn SubmittableTransaction, wallet wallet.Wallet) {
fmt.Printf("Submitting %s transaction...\n", txn.TxType())
flattenedTx := txn.Flatten()
err := client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err := wallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err := client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
fmt.Printf("%s transaction submitted\n", txn.TxType())
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
}

View File

@@ -0,0 +1,344 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/currency"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
const (
currencyCode = "USDA"
)
type SubmittableTransaction interface {
TxType() transactions.TxType
Flatten() transactions.FlatTransaction // Ensures all transactions can be flattened
}
func main() {
fmt.Println("Setting up client...")
client := getClient()
fmt.Println("Connecting to server...")
if err := client.Connect(); err != nil {
panic(err)
}
fmt.Println("Client configured!")
fmt.Println()
fmt.Printf("Connection: %t", client.IsConnected())
fmt.Println()
// Configure wallets
// Issuer
fmt.Println("Setting up issuer wallet...")
issuer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&issuer)
if err != nil {
panic(err)
}
fmt.Printf("Issuer wallet funded: %s\n", issuer.ClassicAddress)
// -----------------------------------------------------
// Holder 1
fmt.Println("Setting up holder 1 wallet...")
holderWallet1, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&holderWallet1)
if err != nil {
panic(err)
}
fmt.Printf("Holder wallet 1 funded: %s\n", holderWallet1.ClassicAddress)
// -----------------------------------------------------
// Holder 2
fmt.Println("Setting up holder 2 wallet...")
holderWallet2, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&holderWallet2)
if err != nil {
panic(err)
}
fmt.Printf("Holder wallet 2 funded: %s\n", holderWallet2.ClassicAddress)
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println()
// -----------------------------------------------------
// Configuring Issuing account
fmt.Println("Configuring issuer address settings...")
accountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
Domain: types.Domain("697373756572"), // issuer
}
accountSet.SetAsfDefaultRipple()
submitAndWait(client, accountSet, issuer)
// -----------------------------------------------------
// Trustline from the holder 1 to the issuer
fmt.Println("Setting up trustline from holder 1 to the issuer...")
trustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "1000000000",
}}
trustSet.SetSetNoRippleFlag()
submitAndWait(client, trustSet, holderWallet1)
// -----------------------------------------------------
// Trustline from the holder 2 to the issuer
fmt.Println("Setting up trustline from holder 2 to the issuer...")
trustSet = &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet2.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "1000000000",
},
}
trustSet.SetSetNoRippleFlag()
submitAndWait(client, trustSet, holderWallet2)
// -----------------------------------------------------
// Minting to Holder 1
fmt.Println("Minting to Holder 1...")
payment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
Destination: types.Address(holderWallet1.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "50000",
},
}
submitAndWait(client, payment, issuer)
// -----------------------------------------------------
// Minting to Holder 2
fmt.Println("Minting to Holder 2...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "40000",
},
}
submitAndWait(client, payment, issuer)
// -----------------------------------------------------
// Sending payment from Holder 1 to Holder 2
fmt.Println("Sending payment from Holder 1 to Holder 2...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "20",
},
}
submitAndWait(client, payment, holderWallet1)
// -----------------------------------------------------
// Freezing and Deep Freezing holder1
fmt.Println("Freezing and Deep Freezing holder 1 trustline...")
trustSet = &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(holderWallet1.ClassicAddress),
Value: "0",
},
}
trustSet.SetSetFreezeFlag()
trustSet.SetSetDeepFreezeFlag()
submitAndWait(client, trustSet, issuer)
// ------------------- SHOULD FAIL ------------------
// Sending payment from Holder 1 to Holder 2 (which should fail), Holder 1 can't decrease its balance
fmt.Println("Sending payment from Holder 1 to Holder 2 (which should fail). Holder 1 can't decrease its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet1)
// ------------------- SHOULD FAIL ------------------
// Sending payment from Holder 2 to Holder 1 (which should fail), Holder 1 can't increase its balance
fmt.Println("Sending payment from Holder 2 to Holder 1 (which should fail). Holder 1 can't increase its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet2.ClassicAddress),
},
Destination: types.Address(holderWallet1.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet2)
// ------------------- SHOULD FAIL ------------------
// Creating OfferCreate transaction (which should fail), Holder 1 can't create an offer
fmt.Println("Creating OfferCreate transaction (which should fail). Holder 1 can't create an offer...")
offerCreate := &transactions.OfferCreate{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
TakerPays: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
TakerGets: types.XRPCurrencyAmount(10),
}
submitAndWait(client, offerCreate, holderWallet1)
// -----------------------------------------------------
// Unfreezing and Deep Unfreezing holder 1
fmt.Println("Unfreezing and Deep Unfreezing holder 1 trustline...")
trustSet = &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(issuer.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(holderWallet1.ClassicAddress),
Value: "0",
},
}
trustSet.SetClearFreezeFlag()
trustSet.SetClearDeepFreezeFlag()
submitAndWait(client, trustSet, issuer)
// -----------------------------------------------------
// Sending payment from Holder 1 to Holder 2 (which should succeed), Holder 1 can decrease its balance
fmt.Println("Sending payment from Holder 1 to Holder 2 (which should succeed). Holder 1 can decrease its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet1.ClassicAddress),
},
Destination: types.Address(holderWallet2.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet1)
// -----------------------------------------------------
// Sending payment from Holder 2 to Holder 1 (which should succeed), Holder 1 can increase its balance
fmt.Println("Sending payment from Holder 2 to Holder 1 (which should succeed). Holder 1 can increase its balance...")
payment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(holderWallet2.ClassicAddress),
},
Destination: types.Address(holderWallet1.ClassicAddress),
Amount: types.IssuedCurrencyAmount{
Currency: currency.ConvertStringToHex(currencyCode),
Issuer: types.Address(issuer.ClassicAddress),
Value: "10",
},
}
submitAndWait(client, payment, holderWallet2)
}
// getRpcClient returns a new rpc client
func getClient() *websocket.Client {
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
return client
}
// submitAndWait submits a transaction and waits for it to be included in a validated ledger
func submitAndWait(client *websocket.Client, txn SubmittableTransaction, wallet wallet.Wallet) {
fmt.Printf("Submitting %s transaction...\n", txn.TxType())
flattenedTx := txn.Flatten()
err := client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err := wallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err := client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
fmt.Printf("%s transaction submitted\n", txn.TxType())
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
}

View File

@@ -8,3 +8,4 @@ For more context, see the Get Started tutorial for your preferred language:
- [Java](https://xrpl.org/get-started-using-java.html) - [Java](https://xrpl.org/get-started-using-java.html)
- [JavaScript](https://xrpl.org/get-started-using-javascript.html) - [JavaScript](https://xrpl.org/get-started-using-javascript.html)
- [PHP](https://xrpl.org/get-started-using-php.html) - [PHP](https://xrpl.org/get-started-using-php.html)
- [Go](https://xrpl.org/get-started-using-go.html)

View File

@@ -0,0 +1,30 @@
package main
import (
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/queries/utility"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
)
func main() {
// Define the network client configuration
cfg, err := rpc.NewClientConfig(
"https://s.altnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
if err != nil {
panic(err)
}
// Initiate the network client
client := rpc.NewClient(cfg)
// Ping the network (used to avoid Go unused variable error, but useful to check connectivity)
_, err = client.Ping(&utility.PingRequest{})
if err != nil {
panic(err)
}
// ... custom code goes here
}

View File

@@ -0,0 +1,25 @@
package main
import (
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
func main() {
// Define the network client
client := websocket.NewClient(websocket.NewClientConfig().
WithHost("wss://s.altnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
// Disconnect the client when done. (Defer executes at the end of the function)
defer client.Disconnect()
// Connect to the network
if err := client.Connect(); err != nil {
panic(err)
}
// ... custom code goes here
}

View File

@@ -0,0 +1,55 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/queries/account"
"github.com/Peersyst/xrpl-go/xrpl/queries/common"
"github.com/Peersyst/xrpl-go/xrpl/queries/ledger"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
// Define the network client with a faucet provider
cfg, err := rpc.NewClientConfig(
"https://s.altnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
// Create a new wallet
w, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("New wallet created:")
fmt.Println("Address:", w.ClassicAddress)
// Fund the wallet with testnet XRP
if err := client.FundWallet(&w); err != nil {
panic(err)
}
// Get info from the ledger about the address we just funded
acc_info, err := client.GetAccountInfo(&account.InfoRequest{
Account: w.GetAddress(),
})
if err != nil {
panic(err)
}
fmt.Println("Account Balance:", acc_info.AccountData.Balance)
fmt.Println("Account Sequence:", acc_info.AccountData.Sequence)
// Get info about the ledger
ledger, err := client.GetLedger(&ledger.Request{LedgerIndex: common.Current})
if err != nil {
panic(err)
}
fmt.Println("Ledger Index:", ledger.Ledger.LedgerIndex)
}

View File

@@ -0,0 +1,69 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/queries/account"
"github.com/Peersyst/xrpl-go/xrpl/queries/common"
"github.com/Peersyst/xrpl-go/xrpl/queries/ledger"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
func main() {
// Define the network client with a faucet provider
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.altnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
// Disconnect the client when done. (Defer executes at the end of the function)
defer client.Disconnect()
// Connect to the network
if err := client.Connect(); err != nil {
panic(err)
}
if !client.IsConnected() {
fmt.Println("Failed to connect to testnet")
return
}
fmt.Println("Connected to testnet")
fmt.Println()
// Create a new wallet
w, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
fmt.Println("New wallet created:")
fmt.Println("Address:", w.ClassicAddress)
// Fund the wallet with testnet XRP
if err := client.FundWallet(&w); err != nil {
panic(err)
}
// Get info from the ledger about the address we just funded
acc_info, err := client.GetAccountInfo(&account.InfoRequest{
Account: w.GetAddress(),
})
if err != nil {
panic(err)
}
fmt.Println("Account Balance:", acc_info.AccountData.Balance)
fmt.Println("Account Sequence:", acc_info.AccountData.Sequence)
// Get info about the ledger
ledger, err := client.GetLedger(&ledger.Request{LedgerIndex: common.Current})
if err != nil {
panic(err)
}
fmt.Println("Ledger Index:", ledger.Ledger.LedgerIndex)
}

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,135 @@
# Get Started Using JavaScript Library
Connects to the XRP Ledger, gets account information, and subscribes to ledger events using JavaScript.
To download the source code, see [Get Started Using JavaScript Library](http://xrpl.org/docs/tutorials/javascript/build-apps/get-started).
## Run the Code
**Node.js**
Quick setup and usage:
```sh
npm install
node ./get-acct-info.js
```
You should see output similar to the following:
```sh
Connected to Testnet
Creating a new wallet and funding it with Testnet XRP...
Wallet: rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i
Balance: 10
Account Testnet Explorer URL:
https://testnet.xrpl.org/accounts/rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i
Getting account info...
{
"api_version": 2,
"id": 4,
"result": {
"account_data": {
"Account": "rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i",
"Balance": "10000000",
"Flags": 0,
"LedgerEntryType": "AccountRoot",
"OwnerCount": 0,
"PreviousTxnID": "0FF9DB2FE141DD0DF82566A171B6AF70BB2C6EB6A53D496E65D42FC062C91A78",
"PreviousTxnLgrSeq": 9949268,
"Sequence": 9949268,
"index": "4A9C9220AE778DC38C004B2B17A08E218416D90E01456AFCF844C18838B36D01"
},
"account_flags": {
"allowTrustLineClawback": false,
"defaultRipple": false,
"depositAuth": false,
"disableMasterKey": false,
"disallowIncomingCheck": false,
"disallowIncomingNFTokenOffer": false,
"disallowIncomingPayChan": false,
"disallowIncomingTrustline": false,
"disallowIncomingXRP": false,
"globalFreeze": false,
"noFreeze": false,
"passwordSpent": false,
"requireAuthorization": false,
"requireDestinationTag": false
},
"ledger_hash": "304C7CC2A33B712BE43EB398B399E290C191A71FCB71784F584544DFB7C441B0",
"ledger_index": 9949268,
"validated": true
},
"type": "response"
}
Listening for ledger close events...
Ledger #9949269 validated with 0 transactions!
Ledger #9949270 validated with 0 transactions!
Ledger #9949271 validated with 0 transactions!
Disconnected
```
**Web**
To run the web example, open `index.html` in a web browser and wait for the results to appear on the page.
You should see output similar to the following:
```text
Connected to Testnet
Creating a new wallet and funding it with Testnet XRP...
Wallet: rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S
Balance: 10
View account on XRPL Testnet Explorer: rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S
Getting account info...
{
"api_version": 2,
"id": 5,
"result": {
"account_data": {
"Account": "rf7CWJdNssSzQk2GtypYLVhyvGe8oHS3S",
"Balance": "10000000",
"Flags": 0,
"LedgerEntryType": "AccountRoot",
"OwnerCount": 0,
"PreviousTxnID": "96E4B44F93EC0399B7ADD75489630C6A8DCFC922F20F6810D25490CC0D3AA12E",
"PreviousTxnLgrSeq": 9949610,
"Sequence": 9949610,
"index": "B5D2865DD4BF8EEDFEE2FD95DE37FC28D624548E9BBC42F9FBF61B618E98FAC8"
},
"account_flags": {
"allowTrustLineClawback": false,
"defaultRipple": false,
"depositAuth": false,
"disableMasterKey": false,
"disallowIncomingCheck": false,
"disallowIncomingNFTokenOffer": false,
"disallowIncomingPayChan": false,
"disallowIncomingTrustline": false,
"disallowIncomingXRP": false,
"globalFreeze": false,
"noFreeze": false,
"passwordSpent": false,
"requireAuthorization": false,
"requireDestinationTag": false
},
"ledger_hash": "7692673B8091899C3EEE6807F66B65851D3563F483A49A5F03A83608658473D6",
"ledger_index": 9949610,
"validated": true
},
"type": "response"
}
Listening for ledger close events...
Ledger #9949611 validated with 0 transactions
Ledger #9949612 validated with 1 transactions
Ledger #9949613 validated with 0 transactions
Disconnected
```

View File

@@ -1,17 +1,11 @@
// In browsers, use a <script> tag. In Node.js, uncomment the following line: // You can also use a <script> tag in browsers or require('xrpl') in Node.js
// const xrpl = require('xrpl') import xrpl from 'xrpl'
// Wrap code in an async function so we can use await // Define the network client
async function main() { const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233")
await client.connect()
// Define the network client // ... custom code goes here
const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233")
await client.connect()
// ... custom code goes here // Disconnect when done (If you omit this, Node.js won't end the process)
client.disconnect()
// Disconnect when done (If you omit this, Node.js won't end the process)
await client.disconnect()
}
main()

View File

@@ -1,39 +1,65 @@
// Import the library // Import the library
const xrpl = require("xrpl") // @chunk {"steps": ["connect-tag"]}
import xrpl from "xrpl"
// Wrap code in an async function so we can use await // Define the network client
async function main() { const SERVER_URL = "wss://s.altnet.rippletest.net:51233/"
const client = new xrpl.Client(SERVER_URL)
await client.connect()
console.log("Connected to Testnet")
// @chunk-end
// Define the network client // @chunk {"steps": ["get-account-create-wallet-tag"]}
const SERVER_URL = "wss://s.altnet.rippletest.net:51233/" // Create a wallet and fund it with the Testnet faucet:
const client = new xrpl.Client(SERVER_URL) console.log("\nCreating a new wallet and funding it with Testnet XRP...")
await client.connect() const fund_result = await client.fundWallet()
const test_wallet = fund_result.wallet
console.log(`Wallet: ${test_wallet.address}`)
console.log(`Balance: ${fund_result.balance}`)
console.log('Account Testnet Explorer URL:')
console.log(` https://testnet.xrpl.org/accounts/${test_wallet.address}`)
// @chunk-end
// Create a wallet and fund it with the Testnet faucet: // To generate a wallet without funding it, uncomment the code below
const fund_result = await client.fundWallet() // @chunk {"steps": ["get-account-create-wallet-b-tag"]}
const test_wallet = fund_result.wallet // const test_wallet = xrpl.Wallet.generate()
console.log(fund_result) // @chunk-end
// Get info from the ledger about the address we just funded // To provide your own seed, replace the test_wallet value with the below
const response = await client.request({ // @chunk {"steps": ["get-account-create-wallet-c-tag"]}
"command": "account_info", // const test_wallet = xrpl.Wallet.fromSeed("your-seed-key")
"account": test_wallet.address, // @chunk-end
"ledger_index": "validated"
})
console.log(response)
// Listen to ledger close events // @chunk {"steps": ["query-xrpl-tag"]}
client.request({ // Get info from the ledger about the address we just funded
"command": "subscribe", console.log("\nGetting account info...")
"streams": ["ledger"] const response = await client.request({
}) "command": "account_info",
client.on("ledgerClosed", async (ledger) => { "account": test_wallet.address,
console.log(`Ledger #${ledger.ledger_index} validated with ${ledger.txn_count} transactions!`) "ledger_index": "validated"
}) })
console.log(JSON.stringify(response, null, 2))
// @chunk-end
// Disconnect when done so Node.js can end the process // @chunk {"steps": ["listen-for-events-tag"]}
await client.disconnect() // Listen to ledger close events
} console.log("\nListening for ledger close events...")
client.request({
"command": "subscribe",
"streams": ["ledger"]
})
client.on("ledgerClosed", async (ledger) => {
console.log(`Ledger #${ledger.ledger_index} validated ` +
`with ${ledger.txn_count} transactions!`)
})
// @chunk-end
// call the async function // @chunk {"steps": ["disconnect-node-tag"]}
main() // Disconnect when done so Node.js can end the process.
// Delay this by 10 seconds to give the ledger event listener time to receive
// and display some ledger events.
setTimeout(async () => {
await client.disconnect();
console.log('\nDisconnected');
}, 10000);
// @chunk-end

View File

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<head>
<title>XRPL.js Base Example</title>
<!-- @chunk {"steps": ["import-web-tag"]} -->
<script src="https://unpkg.com/xrpl/build/xrpl-latest-min.js"></script>
<!-- @chunk-end -->
</head>
<body>
<h1>XRPL.js Get Started</h1>
<div id="output"></div>
<script>
(async () => {
const output = document.getElementById('output');
// @chunk {"steps": ["connect-tag"]}
// Define the network client
const SERVER_URL = "wss://s.altnet.rippletest.net:51233/"
const client = new xrpl.Client(SERVER_URL)
await client.connect()
output.innerHTML = '<p>Connected to Testnet</p>';
// @chunk-end
// @chunk {"steps": ["get-account-create-wallet-tag"]}
// Create a wallet and fund it with the Testnet faucet:
output.innerHTML += '<p>Creating a new wallet and funding it with Testnet XRP...</p>';
const fund_result = await client.fundWallet()
const test_wallet = fund_result.wallet
output.innerHTML += `<p>Wallet: ${test_wallet.address}</p>`;
output.innerHTML += `<p>Balance: ${fund_result.balance}</p>`;
output.innerHTML += `<p>View account on XRPL Testnet Explorer: <a href="https://testnet.xrpl.org/accounts/${test_wallet.address}" target="_blank">${test_wallet.address}</a></p>`;
// @chunk-end
// To generate a wallet without funding it, uncomment the code below
// @chunk {"steps": ["get-account-create-wallet-b-tag"]}
// const test_wallet = xrpl.Wallet.generate()
// @chunk-end
// To provide your own seed, replace the test_wallet value with the below
// @chunk {"steps": ["get-account-create-wallet-c-tag"]}
// const test_wallet = xrpl.Wallet.fromSeed("your-seed-key")
// @chunk-end
// @chunk {"steps": ["query-xrpl-tag"]}
// Get info from the ledger about the address we just funded
output.innerHTML += `<p>Getting account info...</p>`;
const response = await client.request({
"command": "account_info",
"account": test_wallet.address,
"ledger_index": "validated"
})
output.innerHTML += `<pre>${JSON.stringify(response, null, 2)}</pre>`;
// @chunk-end
// @chunk {"steps": ["listen-for-events-tag"]}
// Listen to ledger close events
output.innerHTML += '<p>Listening for ledger close events...</p>';
client.request({
"command": "subscribe",
"streams": ["ledger"]
})
client.on("ledgerClosed", async (ledger) => {
output.innerHTML += `<p>Ledger #${ledger.ledger_index} validated with ${ledger.txn_count} transactions</p>`;
})
// @chunk-end
// @chunk {"steps": ["disconnect-web-tag"]}
// Disconnect when done. Delay this by 10 seconds to give the ledger event listener time to
// receive and display some ledger events.
setTimeout(async () => {
await client.disconnect();
output.innerHTML += '<p>Disconnected</p>';
}, 10000);
// @chunk-end
})();
</script>
</body>
</html>

View File

@@ -1,5 +1,6 @@
{ {
"dependencies": { "dependencies": {
"xrpl": "^4.0.0" "xrpl": "^4.4.0"
} },
"type": "module"
} }

View File

@@ -0,0 +1,23 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,56 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,46 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/xrpl/queries/common"
"github.com/Peersyst/xrpl-go/xrpl/queries/ledger"
"github.com/Peersyst/xrpl-go/xrpl/queries/transactions"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
)
func main() {
cfg, err := rpc.NewClientConfig(
"https://s.altnet.rippletest.net:51234/",
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
// Get the latest validated ledger
led, err := client.GetLedger(&ledger.Request{
Transactions: true,
LedgerIndex: common.Validated,
})
if err != nil {
panic(err)
}
fmt.Println("Latest validated ledger:", led)
// Get the first transaction hash from the ledger
if len(led.Ledger.Transactions) > 0 {
txHash := led.Ledger.Transactions[0].(string) // type assertion may be needed
// Query the transaction details
txResp, err := client.Request(&transactions.TxRequest{
Transaction: txHash,
})
if err != nil {
panic(err)
}
fmt.Println("First transaction in the ledger:")
fmt.Println(txResp)
}
}

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,488 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
const (
currencyCode = "FOO"
)
func main() {
//
// Configure client
//
fmt.Println("Setting up client...")
cfg, err := rpc.NewClientConfig(
"https://s.altnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
fmt.Println("Client configured!")
fmt.Println()
//
// Configure wallets
//
fmt.Println("Setting up wallets...")
coldWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&coldWallet)
if err != nil {
panic(err)
}
fmt.Println("Cold wallet funded!")
hotWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&hotWallet)
if err != nil {
panic(err)
}
fmt.Println("Hot wallet funded!")
customerOneWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&customerOneWallet)
if err != nil {
panic(err)
}
fmt.Println("Customer one wallet funded!")
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println("Cold wallet:", coldWallet.ClassicAddress)
fmt.Println("Hot wallet:", hotWallet.ClassicAddress)
fmt.Println("Customer one wallet:", customerOneWallet.ClassicAddress)
fmt.Println()
//
// Configure cold address settings
//
fmt.Println("Configuring cold address settings...")
coldWalletAccountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
TickSize: types.TickSize(5),
TransferRate: types.TransferRate(0),
Domain: types.Domain("6578616D706C652E636F6D"), // example.com
}
coldWalletAccountSet.SetAsfDefaultRipple()
coldWalletAccountSet.SetDisallowXRP()
coldWalletAccountSet.SetRequireDestTag()
flattenedTx := coldWalletAccountSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err := coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err := client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold address settings configuration failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Cold address settings configured!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Configure hot address settings
//
fmt.Println("Configuring hot address settings...")
hotWalletAccountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
Domain: types.Domain("6578616D706C652E636F6D"), // example.com
}
hotWalletAccountSet.SetAsfRequireAuth()
hotWalletAccountSet.SetDisallowXRP()
hotWalletAccountSet.SetRequireDestTag()
flattenedTx = hotWalletAccountSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Hot address settings configuration failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Hot address settings configured!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Create trust line from hot to cold address
//
fmt.Println("Creating trust line from hot to cold address...")
hotColdTrustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100000000000000",
},
}
flattenedTx = hotColdTrustSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Trust line from hot to cold address creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Trust line from hot to cold address created!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Create trust line from costumer one to cold address
//
fmt.Println("Creating trust line from customer one to cold address...")
customerOneColdTrustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(customerOneWallet.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100000000000000",
},
}
flattenedTx = customerOneColdTrustSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = customerOneWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Trust line from customer one to cold address creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Trust line from customer one to cold address created!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Send tokens from cold wallet to hot wallet
//
fmt.Println("Sending tokens from cold wallet to hot wallet...")
coldToHotPayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "3800",
},
Destination: types.Address(hotWallet.ClassicAddress),
DestinationTag: types.DestinationTag(1),
}
flattenedTx = coldToHotPayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from cold wallet to hot wallet!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Tokens sent from cold wallet to hot wallet!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Send tokens from hot wallet to customer one
//
fmt.Println("Sending tokens from cold wallet to customer one...")
coldToCustomerOnePayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100",
},
Destination: types.Address(customerOneWallet.ClassicAddress),
}
flattenedTx = coldToCustomerOnePayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from cold wallet to customer one!")
fmt.Println()
return
}
fmt.Println("Tokens sent from cold wallet to customer one!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Freeze cold wallet
//
fmt.Println("Freezing cold wallet...")
freezeColdWallet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
}
freezeColdWallet.SetAsfGlobalFreeze()
flattenedTx = freezeColdWallet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold wallet freezing failed!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
return
}
fmt.Println("Cold wallet frozen!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Try to send tokens from hot wallet to customer one
//
fmt.Println("Trying to send tokens from hot wallet to customer one...")
hotToCustomerOnePayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100",
},
Destination: types.Address(customerOneWallet.ClassicAddress),
}
flattenedTx = hotToCustomerOnePayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
_, err = client.SubmitTxBlobAndWait(txBlob, false)
if err == nil {
return
}
fmt.Println("Tokens not sent from hot wallet to customer one!")
fmt.Println()
// //
// // Unfreeze cold wallet
// //
fmt.Println("Unfreezing cold wallet...")
unfreezeColdWallet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
}
unfreezeColdWallet.ClearAsfGlobalFreeze()
flattenedTx = unfreezeColdWallet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold wallet unfreezing failed!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
return
}
fmt.Println("Cold wallet unfrozen!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Try to send tokens from hot wallet to customer one
//
fmt.Println("Trying to send tokens from hot wallet to customer one...")
hotToCustomerOnePayment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100",
},
Destination: types.Address(customerOneWallet.ClassicAddress),
}
flattenedTx = hotToCustomerOnePayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from hot wallet to customer one!")
fmt.Println("Try again!")
return
}
fmt.Println("Tokens sent from hot wallet to customer one!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
}

View File

@@ -0,0 +1,493 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
transactions "github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
const (
currencyCode = "FOO"
)
func main() {
//
// Configure client
//
fmt.Println("Setting up client...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.altnet.rippletest.net").
WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
defer client.Disconnect()
fmt.Println("Client configured!")
fmt.Println()
fmt.Println("Connecting to server...")
if err := client.Connect(); err != nil {
panic(err)
}
fmt.Println("Connection: ", client.IsConnected())
fmt.Println()
//
// Configure wallets
//
fmt.Println("Setting up wallets...")
coldWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&coldWallet)
if err != nil {
panic(err)
}
fmt.Println("Cold wallet funded!")
hotWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&hotWallet)
if err != nil {
panic(err)
}
fmt.Println("Hot wallet funded!")
customerOneWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
err = client.FundWallet(&customerOneWallet)
if err != nil {
panic(err)
}
fmt.Println("Customer one wallet funded!")
fmt.Println()
fmt.Println("Wallets setup complete!")
fmt.Println("Cold wallet:", coldWallet.ClassicAddress)
fmt.Println("Hot wallet:", hotWallet.ClassicAddress)
fmt.Println("Customer one wallet:", customerOneWallet.ClassicAddress)
fmt.Println()
//
// Configure cold address settings
//
fmt.Println("Configuring cold address settings...")
coldWalletAccountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
TickSize: types.TickSize(5),
TransferRate: types.TransferRate(0),
Domain: types.Domain("6578616D706C652E636F6D"), // example.com
}
coldWalletAccountSet.SetAsfDefaultRipple()
coldWalletAccountSet.SetDisallowXRP()
coldWalletAccountSet.SetRequireDestTag()
flattenedTx := coldWalletAccountSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err := coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err := client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold address settings configuration failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Cold address settings configured!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Configure hot address settings
//
fmt.Println("Configuring hot address settings...")
hotWalletAccountSet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
Domain: types.Domain("6578616D706C652E636F6D"), // example.com
}
hotWalletAccountSet.SetAsfRequireAuth()
hotWalletAccountSet.SetDisallowXRP()
hotWalletAccountSet.SetRequireDestTag()
flattenedTx = hotWalletAccountSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Hot address settings configuration failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Hot address settings configured!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Create trust line from hot to cold address
//
fmt.Println("Creating trust line from hot to cold address...")
hotColdTrustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100000000000000",
},
}
flattenedTx = hotColdTrustSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Trust line from hot to cold address creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Trust line from hot to cold address created!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Create trust line from costumer one to cold address
//
fmt.Println("Creating trust line from customer one to cold address...")
customerOneColdTrustSet := &transactions.TrustSet{
BaseTx: transactions.BaseTx{
Account: types.Address(customerOneWallet.ClassicAddress),
},
LimitAmount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100000000000000",
},
}
flattenedTx = customerOneColdTrustSet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = customerOneWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Trust line from customer one to cold address creation failed!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Trust line from customer one to cold address created!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Send tokens from cold wallet to hot wallet
//
fmt.Println("Sending tokens from cold wallet to hot wallet...")
coldToHotPayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "3800",
},
Destination: types.Address(hotWallet.ClassicAddress),
DestinationTag: types.DestinationTag(1),
}
flattenedTx = coldToHotPayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from cold wallet to hot wallet!")
fmt.Println("Try again!")
fmt.Println()
return
}
fmt.Println("Tokens sent from cold wallet to hot wallet!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Send tokens from hot wallet to customer one
//
fmt.Println("Sending tokens from cold wallet to customer one...")
coldToCustomerOnePayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100",
},
Destination: types.Address(customerOneWallet.ClassicAddress),
}
flattenedTx = coldToCustomerOnePayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from cold wallet to customer one!")
fmt.Println()
return
}
fmt.Println("Tokens sent from cold wallet to customer one!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Freeze cold wallet
//
fmt.Println("Freezing cold wallet...")
freezeColdWallet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
}
freezeColdWallet.SetAsfGlobalFreeze()
flattenedTx = freezeColdWallet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold wallet freezing failed!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
return
}
fmt.Println("Cold wallet frozen!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Try to send tokens from hot wallet to customer one
//
fmt.Println("Trying to send tokens from hot wallet to customer one...")
hotToCustomerOnePayment := &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100",
},
Destination: types.Address(customerOneWallet.ClassicAddress),
}
flattenedTx = hotToCustomerOnePayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
_, err = client.SubmitTxBlobAndWait(txBlob, false)
if err == nil {
return
}
fmt.Println("Tokens not sent from hot wallet to customer one!")
fmt.Println()
// //
// // Unfreeze cold wallet
// //
fmt.Println("Unfreezing cold wallet...")
unfreezeColdWallet := &transactions.AccountSet{
BaseTx: transactions.BaseTx{
Account: types.Address(coldWallet.ClassicAddress),
},
}
unfreezeColdWallet.ClearAsfGlobalFreeze()
flattenedTx = unfreezeColdWallet.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = coldWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Cold wallet unfreezing failed!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
return
}
fmt.Println("Cold wallet unfrozen!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
//
// Try to send tokens from hot wallet to customer one
//
fmt.Println("Trying to send tokens from hot wallet to customer one...")
hotToCustomerOnePayment = &transactions.Payment{
BaseTx: transactions.BaseTx{
Account: types.Address(hotWallet.ClassicAddress),
},
Amount: types.IssuedCurrencyAmount{
Currency: currencyCode,
Issuer: types.Address(coldWallet.ClassicAddress),
Value: "100",
},
Destination: types.Address(customerOneWallet.ClassicAddress),
}
flattenedTx = hotToCustomerOnePayment.Flatten()
err = client.Autofill(&flattenedTx)
if err != nil {
panic(err)
}
txBlob, _, err = hotWallet.Sign(flattenedTx)
if err != nil {
panic(err)
}
response, err = client.SubmitTxBlobAndWait(txBlob, false)
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("Tokens not sent from hot wallet to customer one!")
fmt.Println("Try again!")
return
}
fmt.Println("Tokens sent from hot wallet to customer one!")
fmt.Printf("Hash: %s\n", response.Hash.String())
fmt.Println()
}

View File

@@ -0,0 +1,3 @@
# Issue an MPT with Metadata
Shows how to issue a Multi-Purpose Token (MPT) with metadata encoded according to the XLS-89 schema.

View File

@@ -0,0 +1,16 @@
# Issue MPT with Metadata (JavaScript)
Creates a sample MPT issuance with metadata encoded as JSON according to the [XLS-89 standard](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema).
Quick setup and usage:
```sh
npm i
node issue-mpt-with-metadata.js
```
The script should output a validated transaction and end with a line such as the following:
```text
MPToken created successfully with issuance ID 005073C721E14A7613BAAF5E0B1A253459832FF8D0D81278.
```

View File

@@ -0,0 +1,85 @@
import { stringToHex, hexToString } from '@xrplf/isomorphic/dist/utils/index.js'
import { MPTokenIssuanceCreateFlags, Client } from 'xrpl'
// Connect to network and get a wallet
const client = new Client('wss://s.devnet.rippletest.net:51233')
await client.connect()
console.log('Funding new wallet from faucet...')
const { wallet } = await client.fundWallet()
// Define metadata as JSON
const mpt_metadata = {
ticker: 'TBILL',
name: 'T-Bill Yield Token',
desc: 'A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.',
icon: 'https://example.org/tbill-icon.png',
asset_class: 'rwa',
asset_subclass: 'treasury',
issuer_name: 'Example Yield Co.',
urls: [
{
url: 'https://exampleyield.co/tbill',
type: 'website',
title: 'Product Page'
},
{
url: 'https://exampleyield.co/docs',
type: 'docs',
title: 'Yield Token Docs'
}
],
additional_info: {
interest_rate: '5.00%',
interest_type: 'variable',
yield_source: 'U.S. Treasury Bills',
maturity_date: '2045-06-30',
cusip: '912796RX0'
}
}
// Convert JSON to a string (without excess whitespace), then string to hex
const mpt_metadata_hex = stringToHex(JSON.stringify(mpt_metadata))
// Define the transaction, including other MPT parameters
const mpt_issuance_create = {
TransactionType: 'MPTokenIssuanceCreate',
Account: wallet.address,
AssetScale: 4,
MaximumAmount: '50000000',
TransferFee: 0,
Flags: MPTokenIssuanceCreateFlags.tfMPTCanTransfer |
MPTokenIssuanceCreateFlags.tfMPTCanTrade,
MPTokenMetadata: mpt_metadata_hex
}
// Prepare, sign, and submit the transaction
console.log('Sending MPTokenIssuanceCreate transaction...')
const submit_response = await client.submitAndWait(mpt_issuance_create, { wallet, autofill: true })
// Check transaction results and disconnect
console.log(JSON.stringify(submit_response, null, 2))
if (submit_response.result.meta.TransactionResult !== 'tesSUCCESS') {
const result_code = response.result.meta.TransactionResult
console.warn(`Transaction failed with result code ${result_code}.`)
process.exit(1)
}
const issuance_id = submit_response.result.meta.mpt_issuance_id
console.log(`MPToken created successfully with issuance ID ${issuance_id}.`)
// Look up MPT Issuance entry in the validated ledger
console.log('Confirming MPT Issuance metadata in the validated ledger.')
const ledger_entry_response = await client.request({
"command": "ledger_entry",
"mpt_issuance": issuance_id,
"ledger_index": "validated"
})
// Decode the metadata
const metadata_blob = ledger_entry_response.result.node.MPTokenMetadata
const decoded_metadata = JSON.parse(hexToString(metadata_blob))
console.log('Decoded metadata:', decoded_metadata)
client.disconnect()

View File

@@ -0,0 +1,6 @@
{
"dependencies": {
"xrpl": "^4.4.0"
},
"type": "module"
}

View File

@@ -0,0 +1,18 @@
# Issue MPT with Metadata (Python)
Creates a sample MPT issuance with metadata encoded as JSON according to the [XLS-89 standard](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema).
Quick setup and usage:
```sh
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python issue-mpt-with-metadata.py
```
The script should output a validated transaction and end with a line such as the following:
```text
MPToken created successfully with issuance ID 0050773D6B8DF8C6BEA497016C8679728A217DE1C4D50AC5.
```

View File

@@ -0,0 +1,82 @@
import json
from xrpl.utils import str_to_hex, hex_to_str
from xrpl.clients import JsonRpcClient
from xrpl.wallet import generate_faucet_wallet
from xrpl.transaction import submit_and_wait
from xrpl.models import LedgerEntry, MPTokenIssuanceCreate, MPTokenIssuanceCreateFlag
# Set up client and get a wallet
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
print("Funding new wallet from faucet...")
wallet = generate_faucet_wallet(client, debug=True)
# Define metadata as JSON
mpt_metadata = {
"ticker": "TBILL",
"name": "T-Bill Yield Token",
"desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
"icon": "https://example.org/tbill-icon.png",
"asset_class": "rwa",
"asset_subclass": "treasury",
"issuer_name": "Example Yield Co.",
"urls": [
{
"url": "https://exampleyield.co/tbill",
"type": "website",
"title": "Product Page"
},
{
"url": "https://exampleyield.co/docs",
"type": "docs",
"title": "Yield Token Docs"
}
],
"additional_info": {
"interest_rate": "5.00%",
"interest_type": "variable",
"yield_source": "U.S. Treasury Bills",
"maturity_date": "2045-06-30",
"cusip": "912796RX0"
}
}
# Convert JSON to a string (without excess whitespace), then string to hex
mpt_metadata_string = json.dumps(mpt_metadata, separators=(',', ':'))
mpt_metadata_hex = str_to_hex(mpt_metadata_string)
# Define the transaction, including other MPT parameters
mpt_issuance_create = MPTokenIssuanceCreate(
account=wallet.address,
asset_scale=4,
maximum_amount="50000000",
transfer_fee=0,
flags=MPTokenIssuanceCreateFlag.TF_MPT_CAN_TRANSFER |
MPTokenIssuanceCreateFlag.TF_MPT_CAN_TRADE,
mptoken_metadata=mpt_metadata_hex
)
# Prepare, sign, and submit the transaction
print("Sending MPTokenIssuanceCreate transaction...")
response = submit_and_wait(mpt_issuance_create, client, wallet, autofill=True)
print(json.dumps(response.result, indent=2))
# Check transaction results
result_code = response.result["meta"]["TransactionResult"]
if result_code != "tesSUCCESS":
print(f"Transaction failed with result code {result_code}")
exit(1)
issuance_id = response.result["meta"]["mpt_issuance_id"]
print(f"MPToken successfully created with issuance ID {issuance_id}")
# Look up MPT Issuance entry in the validated ledger
print("Confirming MPT Issuance metadata in the validated ledger.")
ledger_entry_response = client.request(LedgerEntry(
mpt_issuance=issuance_id,
ledger_index="validated"
))
# Decode the metadata
metadata_blob = ledger_entry_response.result["node"]["MPTokenMetadata"]
decoded_metadata = json.loads(hex_to_str(metadata_blob))
print("Decoded metadata:", decoded_metadata)

View File

@@ -0,0 +1 @@
xrpl-py==4.3.0

View File

@@ -7,15 +7,15 @@ package main
// install: go get github.com/gorilla/websocket // install: go get github.com/gorilla/websocket
import ( import (
"encoding/json" "encoding/json"
"flag" "flag"
"log" "log"
"net/url" "net/url"
"os" "os"
"os/signal" "os/signal"
"time" "time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
// websocket address // websocket address
@@ -23,75 +23,72 @@ var addr = flag.String("addr", "s.altnet.rippletest.net:51233", "http service ad
// Payload object // Payload object
type message struct { type message struct {
Command string `json:"command"` Command string `json:"command"`
Accounts []string `json:"accounts"` Accounts []string `json:"accounts"`
} }
func main() { func main() {
flag.Parse() flag.Parse()
log.SetFlags(0) log.SetFlags(0)
var m message var m message
// check for interrupts and cleanly close the connection // check for interrupts and cleanly close the connection
interrupt := make(chan os.Signal, 1) interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt) signal.Notify(interrupt, os.Interrupt)
u := url.URL{Scheme: "ws", Host: *addr, Path: "/"} u := url.URL{Scheme: "ws", Host: *addr, Path: "/"}
log.Printf("connecting to %s", u.String()) log.Printf("connecting to %s", u.String())
// make the connection // make the connection
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil { if err != nil {
log.Fatal("dial:", err) panic(err)
} }
// on exit close // on exit close
defer c.Close() defer c.Close()
done := make(chan struct{}) done := make(chan struct{})
// send a subscribe command and a target XRPL account // send a subscribe command and a target XRPL account
m.Command = "subscribe" m.Command = "subscribe"
m.Accounts = append(m.Accounts, "rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM") m.Accounts = append(m.Accounts, "rUCzEr6jrEyMpjhs4wSdQdz4g8Y382NxfM")
// struct to JSON marshalling // struct to JSON marshalling
msg, _ := json.Marshal(m) msg, _ := json.Marshal(m)
// write to the websocket // write to the websocket
err = c.WriteMessage(websocket.TextMessage, []byte(string(msg))) err = c.WriteMessage(websocket.TextMessage, []byte(string(msg)))
if err != nil { if err != nil {
log.Println("write:", err) panic(err)
return }
}
// read from the websocket // read from the websocket
_, message, err := c.ReadMessage() _, message, err := c.ReadMessage()
if err != nil { if err != nil {
log.Println("read:", err) panic(err)
return }
} // print the response from the XRP Ledger
// print the response from the XRP Ledger log.Printf("recv: %s", message)
log.Printf("recv: %s", message)
// handle interrupt // handle interrupt
for { for {
select { select {
case <-done: case <-done:
return return
case <-interrupt: case <-interrupt:
log.Println("interrupt") log.Println("interrupt")
// Cleanly close the connection by sending a close message and then // Cleanly close the connection by sending a close message and then
// waiting (with timeout) for the server to close the connection. // waiting (with timeout) for the server to close the connection.
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil { if err != nil {
log.Println("write close:", err) panic(err)
return }
} select {
select { case <-done:
case <-done: case <-time.After(time.Second):
case <-time.After(time.Second): }
} return
return }
} }
}
} }

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,152 @@
package main
import (
"encoding/hex"
"fmt"
"maps"
"strings"
"github.com/Peersyst/xrpl-go/xrpl"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
cfg, err := rpc.NewClientConfig(
"https://s.altnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
w1, err := wallet.FromSeed("sEdTtvLmJmrb7GaivhWoXRkvU4NDjVf", "")
if err != nil {
panic(err)
}
w2, err := wallet.FromSeed("sEdSFiKMQp7RvYLgH7t7FEpwNRWv2Gr", "")
if err != nil {
panic(err)
}
master, err := wallet.FromSeed("sEdTMm2yv8c8Rg8YHFHQA9TxVMFy1ze", "")
if err != nil {
panic(err)
}
fmt.Println("Funding wallets...")
if err := client.FundWallet(&w1); err != nil {
panic(err)
}
fmt.Println("Wallet 1 funded")
if err := client.FundWallet(&w2); err != nil {
panic(err)
}
fmt.Println("Wallet 2 funded")
if err := client.FundWallet(&master); err != nil {
panic(err)
}
fmt.Println("Master wallet funded")
fmt.Println()
fmt.Println("Setting up signer list...")
ss := &transaction.SignerListSet{
BaseTx: transaction.BaseTx{
Account: master.GetAddress(),
},
SignerQuorum: uint32(2),
SignerEntries: []ledger.SignerEntryWrapper{
{
SignerEntry: ledger.SignerEntry{
Account: w1.GetAddress(),
SignerWeight: 1,
},
},
{
SignerEntry: ledger.SignerEntry{
Account: w2.GetAddress(),
SignerWeight: 1,
},
},
{
SignerEntry: ledger.SignerEntry{
Account: "XVYRdEocC28DRx94ZFGP3qNJ1D5Ln7ecXFMd3vREB5Pesju",
SignerWeight: 1,
},
},
},
}
flatSs := ss.Flatten()
if err := client.Autofill(&flatSs); err != nil {
panic(err)
}
blob, _, err := master.Sign(flatSs)
if err != nil {
panic(err)
}
res, err := client.SubmitTxBlobAndWait(blob, false)
if err != nil {
panic(err)
}
fmt.Println("SignerListSet transaction submitted!")
fmt.Printf("Hash: %s\n", res.Hash.String())
fmt.Println()
fmt.Println("Setting up AccountSet multisign transaction...")
as := &transaction.AccountSet{
BaseTx: transaction.BaseTx{
Account: master.GetAddress(),
},
Domain: types.Domain(strings.ToUpper(hex.EncodeToString([]byte("example.com")))),
}
flatAs := as.Flatten()
if err := client.AutofillMultisigned(&flatAs, 2); err != nil {
panic(err)
}
w1As := maps.Clone(flatAs)
blob1, _, err := w1.Multisign(w1As)
if err != nil {
panic(err)
}
w2As := maps.Clone(flatAs)
blob2, _, err := w2.Multisign(w2As)
if err != nil {
panic(err)
}
blob, err = xrpl.Multisign(blob1, blob2)
if err != nil {
panic(err)
}
mRes, err := client.SubmitMultisigned(blob, false)
if err != nil {
panic(err)
}
fmt.Println("Multisigned transaction submitted!")
fmt.Printf("Result: %s\n", mRes.EngineResult)
}

View File

@@ -0,0 +1,166 @@
package main
import (
"encoding/hex"
"fmt"
"maps"
"strings"
"github.com/Peersyst/xrpl-go/xrpl"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
func main() {
fmt.Println("Connecting to testnet...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.altnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewTestnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
if !client.IsConnected() {
fmt.Println("Failed to connect to testnet")
return
}
fmt.Println("Connected to testnet")
fmt.Println()
w1, err := wallet.FromSeed("sEdTtvLmJmrb7GaivhWoXRkvU4NDjVf", "")
if err != nil {
panic(err)
}
w2, err := wallet.FromSeed("sEdSFiKMQp7RvYLgH7t7FEpwNRWv2Gr", "")
if err != nil {
panic(err)
}
master, err := wallet.FromSeed("sEdTMm2yv8c8Rg8YHFHQA9TxVMFy1ze", "")
if err != nil {
panic(err)
}
fmt.Println("Funding wallets...")
if err := client.FundWallet(&w1); err != nil {
panic(err)
}
fmt.Println("Wallet 1 funded")
if err := client.FundWallet(&w2); err != nil {
panic(err)
}
fmt.Println("Wallet 2 funded")
if err := client.FundWallet(&master); err != nil {
panic(err)
}
fmt.Println("Master wallet funded")
fmt.Println()
fmt.Println("Setting up signer list...")
ss := &transaction.SignerListSet{
BaseTx: transaction.BaseTx{
Account: master.GetAddress(),
},
SignerQuorum: uint32(2),
SignerEntries: []ledger.SignerEntryWrapper{
{
SignerEntry: ledger.SignerEntry{
Account: w1.GetAddress(),
SignerWeight: 1,
},
},
{
SignerEntry: ledger.SignerEntry{
Account: w2.GetAddress(),
SignerWeight: 1,
},
},
{
SignerEntry: ledger.SignerEntry{
Account: "XVYRdEocC28DRx94ZFGP3qNJ1D5Ln7ecXFMd3vREB5Pesju",
SignerWeight: 1,
},
},
},
}
fmt.Println("Flattening transaction...")
flatSs := ss.Flatten()
fmt.Println("Autofilling transaction...")
if err := client.Autofill(&flatSs); err != nil {
panic(err)
}
fmt.Println("Signing transaction...")
blob, _, err := master.Sign(flatSs)
if err != nil {
panic(err)
}
fmt.Println("Submitting transaction...")
res, err := client.SubmitTxBlobAndWait(blob, false)
if err != nil {
panic(err)
}
fmt.Println("SignerListSet transaction submitted!")
fmt.Printf("Hash: %s\n", res.Hash.String())
fmt.Println()
fmt.Println("Setting up AccountSet multisign transaction...")
as := &transaction.AccountSet{
BaseTx: transaction.BaseTx{
Account: master.GetAddress(),
},
Domain: types.Domain(strings.ToUpper(hex.EncodeToString([]byte("example.com")))),
}
flatAs := as.Flatten()
if err := client.AutofillMultisigned(&flatAs, 2); err != nil {
panic(err)
}
w1As := maps.Clone(flatAs)
blob1, _, err := w1.Multisign(w1As)
if err != nil {
panic(err)
}
w2As := maps.Clone(flatAs)
blob2, _, err := w2.Multisign(w2As)
if err != nil {
panic(err)
}
blob, err = xrpl.Multisign(blob1, blob2)
if err != nil {
panic(err)
}
mRes, err := client.SubmitMultisigned(blob, false)
if err != nil {
panic(err)
}
fmt.Println("Multisigned transaction submitted!")
fmt.Printf("Result: %s\n", mRes.EngineResult)
}

View File

@@ -0,0 +1,24 @@
module github.com/XRPLF
go 1.23.0
toolchain go1.23.10
require github.com/Peersyst/xrpl-go v0.1.11
require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.35.0 // indirect
)

View File

@@ -0,0 +1,58 @@
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Peersyst/xrpl-go v0.1.11 h1:P6r/gHxRnbAtAdPmzNHz/7zpsdfvwh0SS+QI2JNT44w=
github.com/Peersyst/xrpl-go v0.1.11/go.mod h1:CBRM3/soqNeeL2Jx6USVUtECqulZVUoq3UxZKMz9hdw=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

View File

@@ -0,0 +1,122 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/rpc/types"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
// Initialize the RPC client configuration
cfg, err := rpc.NewClientConfig(
"https://s.devnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}
// Create the RPC client
client := rpc.NewClient(cfg)
// Step 1: Fund wallets
fmt.Println("Funding wallets...")
// Create and fund the NFT minter wallet
nftMinter, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftMinter); err != nil {
panic(err)
}
fmt.Println("NFT minter wallet funded!")
// Create and fund the NFT buyer wallet
nftBuyer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftBuyer); err != nil {
panic(err)
}
fmt.Println("NFT buyer wallet funded!")
fmt.Println()
// Step 2: Mint an NFT
fmt.Println("Minting NFT...")
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
Destination: nftBuyer.ClassicAddress,
Amount: txnTypes.XRPCurrencyAmount(1000000), // 1 XRP
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint)
return
}
fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
// Step 3: Retrieve the NFT token offer ID
fmt.Println("Retrieving NFT offer ID...")
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
offerID, ok := metaMap["offer_id"].(string)
if !ok {
fmt.Println("offer_id not found or not a string")
return
}
fmt.Println("offer_id:", offerID)
fmt.Println()
// Step 4: Accept the NFT offer
fmt.Println("Accepting NFT offer...")
nftAccept := transaction.NFTokenAcceptOffer{
BaseTx: transaction.BaseTx{
Account: nftBuyer.ClassicAddress,
TransactionType: transaction.NFTokenAcceptOfferTx,
},
NFTokenSellOffer: txnTypes.Hash256(offerID),
}
response, err := client.SubmitTxAndWait(nftAccept.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftBuyer,
})
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("NFTokenAcceptOffer txn is not in a validated ledger", response)
return
}
fmt.Println("NFT offer accepted successfully! - Hash: ", response.Hash)
}

View File

@@ -0,0 +1,126 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
"github.com/Peersyst/xrpl-go/xrpl/websocket/types"
)
func main() {
// Connect to the XRPL devnet
fmt.Println("Connecting to devnet...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
if !client.IsConnected() {
fmt.Println("Failed to connect to devnet")
return
}
fmt.Println("Connected to devnet")
fmt.Println()
// Fund wallets
fmt.Println("Funding wallets...")
// Create and fund the NFT minter wallet
nftMinter, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftMinter); err != nil {
panic(err)
}
fmt.Println("NFT minter wallet funded!")
// Create and fund the NFT buyer wallet
nftBuyer, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftBuyer); err != nil {
panic(err)
}
fmt.Println("NFT buyer wallet funded!")
fmt.Println()
// Mint an NFT
fmt.Println("Minting NFT...")
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
Destination: nftBuyer.ClassicAddress,
Amount: txnTypes.XRPCurrencyAmount(1000000), // 1 XRP
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("NFTokenMint transaction is not in a validated ledger:", responseMint)
return
}
fmt.Println("NFT minted successfully! - Hash:", responseMint.Hash)
fmt.Println()
// Extract the NFT token offer ID from the transaction metadata
fmt.Println("Extracting offer ID...")
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
offerID, ok := metaMap["offer_id"].(string)
if !ok {
fmt.Println("offer_id not found or not a string")
return
}
fmt.Println("offer_id:", offerID)
fmt.Println()
// Accept the NFT offer
fmt.Println("Accepting NFT offer...")
nftAccept := transaction.NFTokenAcceptOffer{
BaseTx: transaction.BaseTx{
Account: nftBuyer.ClassicAddress,
TransactionType: transaction.NFTokenAcceptOfferTx,
},
NFTokenSellOffer: txnTypes.Hash256(offerID),
}
response, err := client.SubmitTxAndWait(nftAccept.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftBuyer,
})
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("NFTokenAcceptOffer transaction is not in a validated ledger:", response)
return
}
fmt.Println("NFT offer accepted successfully! - Hash:", response.Hash)
}

View File

@@ -0,0 +1,110 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/rpc/types"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
// Initialize the RPC client configuration
cfg, err := rpc.NewClientConfig(
"https://s.devnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}
// Create the RPC client
client := rpc.NewClient(cfg)
// Step 1: Fund wallets
fmt.Println("Funding wallets...")
// Create and fund the NFT minter wallet
nftMinter, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftMinter); err != nil {
panic(err)
}
fmt.Println("NFT minter wallet funded!")
fmt.Println()
// Step 2: Mint an NFT
fmt.Println("Minting NFT...")
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint)
return
}
fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
// Step 3: Retrieve the token ID
fmt.Println("Retrieving NFT ID...")
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID, ok := metaMap["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID)
fmt.Println()
// Step 4: Burn the NFT
fmt.Println("Burn the NFT...")
nftBurn := transaction.NFTokenBurn{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenAcceptOfferTx,
},
NFTokenID: txnTypes.NFTokenID(nftokenID),
}
responseBurn, err := client.SubmitTxAndWait(nftBurn.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseBurn.Validated {
fmt.Println("NFTokenBurn transactiob is not in a validated ledger", responseBurn)
return
}
fmt.Println("NFT burned successfully! - Hash: ", responseBurn.Hash)
}

View File

@@ -0,0 +1,118 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
"github.com/Peersyst/xrpl-go/xrpl/websocket/types"
)
func main() {
// Connect to the XRPL devnet
fmt.Println("Connecting to devnet...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
if !client.IsConnected() {
fmt.Println("Failed to connect to devnet")
return
}
fmt.Println("Connected to devnet")
fmt.Println()
// Step 1: Fund wallets
fmt.Println("Funding wallets...")
// Create and fund the NFT minter wallet
nftMinter, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftMinter); err != nil {
panic(err)
}
fmt.Println("NFT minter wallet funded!")
fmt.Println()
// Step 2: Mint an NFT
fmt.Println("Minting NFT...")
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint)
return
}
fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
// Step 3: Retrieve the token ID
fmt.Println("Retrieving NFT ID...")
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID, ok := metaMap["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID)
fmt.Println()
// Step 4: Burn the NFT
fmt.Println("Burn the NFT...")
nftBurn := transaction.NFTokenBurn{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenAcceptOfferTx,
},
NFTokenID: txnTypes.NFTokenID(nftokenID),
}
responseBurn, err := client.SubmitTxAndWait(nftBurn.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseBurn.Validated {
fmt.Println("NFTokenBurn transactiob is not in a validated ledger", responseBurn)
return
}
fmt.Println("NFT burned successfully! - Hash: ", responseBurn.Hash)
}

View File

@@ -0,0 +1,158 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/rpc/types"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
// Initialize the RPC client configuration
cfg, err := rpc.NewClientConfig(
"https://s.devnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}
// Create the RPC client
client := rpc.NewClient(cfg)
// Step 1: Fund wallet
fmt.Println("Funding wallet...")
// Create and fund the NFT minter wallet
nftMinter, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftMinter); err != nil {
panic(err)
}
fmt.Println("NFT minter wallet funded!")
// Step 2: Mint two NFTs
fmt.Println("Minting first NFT...")
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("First NFTokenMint transaction is not in a validated ledger", responseMint)
return
}
fmt.Println("First NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
// Step 3: Retrieve the NFT token ID
fmt.Println("Retrieving NFT ID...")
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID1, ok := metaMap["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID1)
fmt.Println()
// ------
fmt.Println("Minting second NFT...")
nftMint2 := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint2.SetTransferableFlag()
responseMint2, err := client.SubmitTxAndWait(nftMint2.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("Second NFTokenMint transaction is not in a validated ledger", responseMint)
return
}
fmt.Println("Second NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
// Step 3: Retrieve the second NFT token ID
fmt.Println("Retrieving second NFT ID...")
metaMap2, ok := responseMint2.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID2, ok := metaMap2["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID2)
fmt.Println()
// Step 4: Cancel the NFT offers
fmt.Println("Canceling NFT offers...")
nftCancel := transaction.NFTokenCancelOffer{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenAcceptOfferTx,
},
NFTokenOffers: []txnTypes.NFTokenID{
txnTypes.NFTokenID(nftokenID1),
txnTypes.NFTokenID(nftokenID2),
},
}
response, err := client.SubmitTxAndWait(nftCancel.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("NFTokenCancelOffer transaction is not in a validated ledger", response)
return
}
fmt.Println("NFT offers canceled successfully! - Hash: ", response.Hash)
}

View File

@@ -0,0 +1,166 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
"github.com/Peersyst/xrpl-go/xrpl/websocket/types"
)
func main() {
// Connect to the XRPL devnet
fmt.Println("Connecting to devnet...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
if !client.IsConnected() {
fmt.Println("Failed to connect to devnet")
return
}
fmt.Println("Connected to devnet")
fmt.Println()
// Step 1: Fund wallet
fmt.Println("Funding wallet...")
// Create and fund the NFT minter wallet
nftMinter, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftMinter); err != nil {
panic(err)
}
fmt.Println("NFT minter wallet funded!")
// Step 2: Mint two NFTs
fmt.Println("Minting first NFT...")
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("First NFTokenMint transaction is not in a validated ledger", responseMint)
return
}
fmt.Println("First NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
// Step 3: Retrieve the NFT token ID
fmt.Println("Retrieving NFT ID...")
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID1, ok := metaMap["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID1)
fmt.Println()
// ------
fmt.Println("Minting second NFT...")
nftMint2 := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint2.SetTransferableFlag()
responseMint2, err := client.SubmitTxAndWait(nftMint2.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("Second NFTokenMint transaction is not in a validated ledger", responseMint)
return
}
fmt.Println("Second NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
// Step 3: Retrieve the second NFT token ID
fmt.Println("Retrieving second NFT ID...")
metaMap2, ok := responseMint2.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID2, ok := metaMap2["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID2)
fmt.Println()
// Step 4: Cancel the NFT offers
fmt.Println("Canceling NFT offers...")
nftCancel := transaction.NFTokenCancelOffer{
BaseTx: transaction.BaseTx{
Account: nftMinter.ClassicAddress,
TransactionType: transaction.NFTokenAcceptOfferTx,
},
NFTokenOffers: []txnTypes.NFTokenID{
txnTypes.NFTokenID(nftokenID1),
txnTypes.NFTokenID(nftokenID2),
},
}
response, err := client.SubmitTxAndWait(nftCancel.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftMinter,
})
if err != nil {
panic(err)
}
if !response.Validated {
fmt.Println("NFTokenCancelOffer transaction is not in a validated ledger", response)
return
}
fmt.Println("NFT offers canceled successfully! - Hash: ", response.Hash)
}

View File

@@ -0,0 +1,103 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/rpc"
"github.com/Peersyst/xrpl-go/xrpl/rpc/types"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
)
func main() {
cfg, err := rpc.NewClientConfig(
"https://s.devnet.rippletest.net:51234/",
rpc.WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
if err != nil {
panic(err)
}
client := rpc.NewClient(cfg)
fmt.Println()
fmt.Println("Funding wallet...")
// Create and fund the nft wallet
nftWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftWallet); err != nil {
panic(err)
}
fmt.Println("NFT wallet funded: ", nftWallet.ClassicAddress)
fmt.Println()
// Mint NFT
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftWallet.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetMutableFlag()
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftWallet,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint)
return
}
fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID, ok := metaMap["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID)
fmt.Println()
// Update NFT
nftModify := transaction.NFTokenModify{
BaseTx: transaction.BaseTx{
Account: nftWallet.ClassicAddress,
TransactionType: transaction.NFTokenModifyTx,
},
URI: "68747470733A2F2F7961686F6F2E636F6D", // https://yahoo.com
NFTokenID: txnTypes.NFTokenID(nftokenID),
}
// nftoken_id
responseModify, err := client.SubmitTxAndWait(nftModify.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftWallet,
})
if err != nil {
panic(err)
}
if !responseModify.Validated {
fmt.Println("NFTokenModify txn is not in a validated ledger", responseModify)
return
}
fmt.Println("NFT URI modified successfully! - Hash: ", responseModify.Hash)
}

View File

@@ -0,0 +1,112 @@
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/pkg/crypto"
"github.com/Peersyst/xrpl-go/xrpl/faucet"
"github.com/Peersyst/xrpl-go/xrpl/transaction"
txnTypes "github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/wallet"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
"github.com/Peersyst/xrpl-go/xrpl/websocket/types"
)
func main() {
fmt.Println("Connecting to devnet...")
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233").
WithFaucetProvider(faucet.NewDevnetFaucetProvider()),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
if !client.IsConnected() {
fmt.Println("Failed to connect to devnet")
return
}
fmt.Println("Connected to devnet")
fmt.Println()
// Create and fund the nft wallet
fmt.Println("Funding wallet...")
nftWallet, err := wallet.New(crypto.ED25519())
if err != nil {
panic(err)
}
if err := client.FundWallet(&nftWallet); err != nil {
panic(err)
}
fmt.Println("NFT wallet funded!")
fmt.Println()
// Mint NFT
nftMint := transaction.NFTokenMint{
BaseTx: transaction.BaseTx{
Account: nftWallet.ClassicAddress,
TransactionType: transaction.NFTokenMintTx,
},
NFTokenTaxon: 0,
URI: txnTypes.NFTokenURI("68747470733A2F2F676F6F676C652E636F6D"), // https://google.com
}
nftMint.SetMutableFlag()
nftMint.SetTransferableFlag()
responseMint, err := client.SubmitTxAndWait(nftMint.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftWallet,
})
if err != nil {
panic(err)
}
if !responseMint.Validated {
fmt.Println("NFTokenMint txn is not in a validated ledger", responseMint)
return
}
fmt.Println("NFT minted successfully! - Hash: ", responseMint.Hash)
fmt.Println()
metaMap, ok := responseMint.Meta.(map[string]any)
if !ok {
fmt.Println("Meta is not a map[string]any")
return
}
nftokenID, ok := metaMap["nftoken_id"].(string)
if !ok {
fmt.Println("nftoken_id not found or not a string")
return
}
fmt.Println("nftoken_id:", nftokenID)
fmt.Println()
// Update NFT
nftModify := transaction.NFTokenModify{
BaseTx: transaction.BaseTx{
Account: nftWallet.ClassicAddress,
TransactionType: transaction.NFTokenModifyTx,
},
URI: "68747470733A2F2F7961686F6F2E636F6D", // https://yahoo.com
NFTokenID: txnTypes.NFTokenID(nftokenID),
}
responseModify, err := client.SubmitTxAndWait(nftModify.Flatten(), &types.SubmitOptions{
Autofill: true,
Wallet: &nftWallet,
})
if err != nil {
panic(err)
}
if !responseModify.Validated {
fmt.Println("NFTokenModify txn is not in a validated ledger", responseModify)
return
}
fmt.Println("NFT URI modified successfully! - Hash: ", responseModify.Hash)
}

Some files were not shown because too many files have changed in this diff Show More