Coder Social home page Coder Social logo

ergo-appkit's People

Contributors

anon2020s avatar aslesarenko avatar dav009 avatar greenhat avatar k-singh avatar mgpai22 avatar mrstahlfelge avatar robkorn avatar scalahub avatar vorujack avatar wclaeys avatar zargarzadehm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ergo-appkit's Issues

Add way to find out what went wrong when sendTransaction fails

BlockChainContext.sendTransaction returns null or an empty string if no transaction could be made. However, it would be good to let the calling application know what went wrong. This could be done by throwing an error containing Retrofit's call object with more information.

SPV workflow for verifying a payment with NiPoPoW

SPV workflow for verifying a payment with NiPoPoW

Created from ergo-lib #495

Using NiPoPoW described in KMZ17

Goal

Prove that a payment (ERG and/or tokens) was made on the blockchain.

EDIT: For a recent payment it would be faster to use UTXO proof described in #502

Step 1. Prove that a tx with a given id in a block with a given id exists in the blockchain.

Step 1.1. Prove that a block with a given id exists in the blockchain.

Step 1.2. Prove that a tx with a given id exists in the blockchain.

See Step 1.1 in ergo-lib example workflow

Step 2. Check the box with the payment

Step 2.1 Get the whole tx for tx id from Step 1

It can either be provided along with the tx id in Step 1 or fetched from the node. It is verified by serializing the tx and calculating its id and then comparing it to the tx id confirmed in Step 1.2.

Step 2.2. Confirm the payment is in this tx

Find the output box protected with a certain script (e.g certain PK) and check that its value and/or tokens are as expected.

Implement the missing parts in appkit:

  • REST API calls support mentioned above;
  • move NipopowProof, NipopowVerifier, and all dependent types from node code into a lib (ergo-wallet?) ergoplatform/ergo#1965
  • expose NipopowProof, NipopowVerifier, MerkleProof with mentioned above properties/methods in appkit public API.

EDIT: Actually, I'm pretty sure that the above NiPoPoW-related types would better be in a dedicated ergo-nipopow lib since they are not directly related to wallet features. However, the bigger challenge will be the dependent more low-level types like Header, etc. Seems like they should be moved to their own separate lib (ergo-core/ergo-chain-types?).

Tokens get burned if input box contains 2 entries for the same token

In some cases boxes can be created with 2 entries for the same token, for example on entry with 2k migoreng and one entry with 6k migoreng.

The appkit seems to only count one of these entries when creating the change box, causing the rest to be burned.

An example of a box with duplicate token entries can be seen in the output of this tx:
https://explorer.ergoplatform.com/en/transactions/02b425ed91ca655cb39f83febbcd0efed6114a05f8b7eb69324042b2372060c5

Generate commands list as Markdown table

Problem

Each CliApplication implements a list of commands.
This list can be printed in console output as part of usage help message.
However, it is usually required to have this list also in a documentation page.
The corresponding section of the doc page can thus be generated for any CliApplication instance.

Solution

Implement the genMarkdown method which uses commands method for a list of supported commands.

Example

Implement generic builder of ErgoValue for Scala

Construction of ErgoValue instances with complex types of value is problematic, because ErgoValue is implemented with Java types, which makes it easier to be used from Java.

This issue is to implement generic builder

val x: Coll[(Coll[(Byte, Long)], Coll[Byte])] = ...

val ev = ErgoValueBuilder.buildFor(x)

Some transactions fail to sign with appkit, succeed with node

Some of my pure p2s transactions reduce to false with the appkit but sign fine using the node.

Testnet example:
UnsignedTx:
{'inputs': [{'boxId': '6ee4d5d0dc518d52386cef251efa732680a8600ecac87ee3ad95c7aa1d8282b3', 'value': '1000000', 'ergoTree': '104e0402040004020400040204000400040204020404040404060406040004000408040404080e20ec7db8b46327614a657fe8f7391a9c264d86b7aca5832d52148ce1e38436dc6b0e20b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f30500040204000406040404020404040005020502040004020580dddb01050205d00f040205020402040204020404040004000502040404000402050201000e208557834f67bdc177ee9528d7d0faf33ef025666f1f45a70e7e57d32f327dcec40404050204000e2083759b1a3d080d043db81acd10e1a6cb5b6fff8815b32c0ccc3380a9691ad909040205020404050001000402040204000500040404000502050005020500050004000402040004020402040205d00f0100d829d601b2a5730000d602db63087201d603b27202730100d6048c720301d605db6308a7d606b27205730200d6078c720601d6089372047207d609b2a5730300d60adb63087209d60bb2720a730400d60c8c720b02d60d8c720602d60ee4c6a70411d60fb2720e730500d610e4c672090411d611b27210730600d612b27210730700d613b2720e730800d614b2720e730900d615b27210730a00d616b27210730b00d617b2720e730c00d618b2720a730d00d619b27205730e00d61ab2720e730f00d61b9683070193c17209c1a793c27209c2a7938c7218018c721901938c7218028c721902938c720b01720793b1720a731093b27210731100721ad61c7312d61ddb6903db6503fed61e8c720302d61f7313d62086028300027314d621b2a4731500d622db63087221d623b27222731600d6248c722301d62592b1a47317d626e4c672210411d627e4c67221050ed628b2a5731800d629db63087228d1ecec957208958f720c720dd806d62ab27202731900d62b8c722a02d62ce4c672010411d62de4c67201050ed62eb2a5731a00d62fb2db6308722e731b009683030196830601721b9372119a720f722b93721272139372159a7214731c937216721793720c99720d731d9683080193cbc27201721c93b2722c731e00721392b2722c731f0099721d732093722dc5a7720893721e7321938c722a01721f92722b73229683030193c2722ee4c6b2a4732300050e938c722f01722d938c722f027324d807d62ab27202732500d62b8c722a02d62cb2a4732600d62d8cb2db6308722c732701722002d62ee4c672010411d62fe4c67201050ed630b2db6308b2a57328007329009683030196830601721b9372119a720f99722b722d93721272139372157214937216721793720c720d96830a0193c17201c1722c93cbc27201721c93cbc2722c721c93b2722e732a00721393722ee4c6722c041193722fe4c6722c050e720893721e732b938c722a01721f93722b9a722d8cb2db6308b2a4732c01b2a4732d00732e000296830201938c723001722f938c723002732f7330959683020193722473317225d802d62ab2a4733200d62be4c6722a04119683020196830601721b9372129a7213733393721572149372169a7217721a8f7216721d93720c720d96830301938cb2db6308722a73340001733593b2722b733600997213733793b2722b7338007339733a959683030191720f7211722591b17222733bd807d62ab27222733c00d62b99720f7211d62c998c722a02722bd62d8c722a01d62eb27226733d00d62f90722c733ed6309683040196830201937224720793722e7213938cb2db6308b2a4733f0073400001722796830601721b93721199720f722b937212721393721599721495722f73417342937216721793720c9a720d95722f7343734496830201937204722d93721e722b9591722c7345d803d631b272297346017220d632b27229734700d633e4c672280411968303017230968302019683080193c17228c1722193c27228c27221938c7231017224938c7231028c722302938c723201722d938c723202722c93b27233734800722e93b27233734900b27226734a00938cb27202734b01722001722792722c734c7230734d', 'creationHeight': 257321, 'assets': [{'tokenId': '99272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e647', 'amount': '1'}, {'tokenId': '21038855e00a9e767ffbeb9bbc1f59c39555e9e11652dcb5a0f689b53d78b197', 'amount': '999999999988'}], 'additionalRegisters': {'R4': '110580d30e00188098fe96a56080f0b252'}, 'transactionId': '423909c8e0f1354694bc7a74711cc41e10b577f36d1608e89454983ed389276e', 'index': 0, 'extension': {}}, {'boxId': 'a9322bc7e71916285855645ef65bd873c48e840ca4ca0e341fdb50721ced1375', 'value': '1000000', 'ergoTree': '101d040004000e2099272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e6470402040204020404040404020500040005c80104060400040004020402040004000400040204000e240008cd02189359b825e96aa3c7af90c9958d85daf8f86358382db3306e024c5aeea1e8ec0580897a01010100040004000100d802d601b2a4730000d602c5a7d1ec9596830201938cb2db6308720173010001730293c5b2a47303007202d80cd603b2a5730400d604db63087203d605db6308a7d606b27205730500d607db6308b2a4730600d6089592b1720773078cb27207730800027309d6099a8c7206027208d60ae4c6a70411d60bb2720a730a00d60c8c720601d60d9d720b730bd60eb2a5730c00968302019683070193c17203c1a793c27203c2a7938cb27204730d00018cb27205730e000195917209720bd801d60fb27204730f0096830201938c720f01720c938c720f02997209720b93b17204731093e4c672030411720a93e4c67203050ee4c6a7050e93b2e4c6b2a57311000411731200999ab2e4c67201041173130099720b720d72089591b172047314d801d60fb2db6308720e7315009683040193c2720e731693c1720e7317938c720f01720c938c720f02720d731873199593c572017202938cb2db6308b2a5731a00731b0001e4c6a7050e731c', 'creationHeight': 257244, 'assets': [{'tokenId': '8557834f67bdc177ee9528d7d0faf33ef025666f1f45a70e7e57d32f327dcec4', 'amount': '1'}, {'tokenId': 'b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f3', 'amount': '50000000000'}], 'additionalRegisters': {'R4': '1101a0cda38502', 'R5': '0e2014d5b543223eb8e67ea70c1884118122c77dfb0020140fc93cedded89186e582'}, 'transactionId': '70201e1fbd3067905ac77b7a3e58076b78995e1e9a347a303fd7d0bef2d7e7af', 'index': 1, 'extension': {}}, {'boxId': '0361723110b35154298317f604d645af873060970067b9867c4b835225063a3a', 'value': '1000000', 'ergoTree': '102d0400040404020e20b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f3040004000e2099272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e6470404040604000402040205000402040004060400040605c8010400040001000402040004000e2021038855e00a9e767ffbeb9bbc1f59c39555e9e11652dcb5a0f689b53d78b197040004020100040606010004020400040004000402040204000404040004040404040404060100d807d601b2a4730000d602c5a7d603b2a5730100d604b2a4730200d6057303d606b2a5730400d607db6308a7d1ec9596830201938cb2db6308720173050001730693c5b2a47307007202d807d608e4c672030411d609b27208730800d60ab2e4c672040411730900d60bdb6308a7d60c9a8cb2db63087204730a00028cb2720b730b018602830002730c02d60ddb63087203d60eb2720d730d009683070193c17203c1a793c27203c2a793b47208730e730fb4e4c67201041173107311937209958f720a720c99720a9d720a7312720c938cb2720d731300018cb2720b73140001938c720e017205938c720e02720973159593c572017202d807d608db63087206d6097e8cb272077316000206d60ab5a4d9010a63d801d60cdb6308720a9591b1720c7317ed938cb2720c73180001731993b2e4c6720a0411731a00b2e4c6a70411731b00731cd60be4c6a70411d60cb2720b731d00d60db0720a731ed9010d42639a8c720d019d9c7e8cb2db63088c720d02731f0002067e720c067eb2720b73200006d60ee4c6720604119683070193c17206c1a793c27206c2a7938cb27208732100018cb272077322000195907209720d93b172087323d801d60fb27208732400ed938c720f017205927e8c720f0206997209720d93b4720e73257326b4720b7327732893b2720e73290099b2720b732a007eb1720a0593b2720e732b00720c732c', 'creationHeight': 257244, 'assets': [{'tokenId': '83759b1a3d080d043db81acd10e1a6cb5b6fff8815b32c0ccc3380a9691ad909', 'amount': '1'}], 'additionalRegisters': {'R4': '1104000100a0cda38502'}, 'transactionId': '70201e1fbd3067905ac77b7a3e58076b78995e1e9a347a303fd7d0bef2d7e7af', 'index': 2, 'extension': {}}, {'boxId': '33c2e2f9e6c9cbb6f3e8e9290deaee980d8c0ac202f2272cb85cb27bc6344cf1', 'value': '100000000', 'ergoTree': '102f048084af5f04060400040205c0843d04040580897a010005000e2083759b1a3d080d043db81acd10e1a6cb5b6fff8815b32c0ccc3380a9691ad9090406040004000e2099272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e6470404040004020100040805809bee020580897a0580897a040a05809bee02040c0580897a0100040004020400040004000e2021038855e00a9e767ffbeb9bbc1f59c39555e9e11652dcb5a0f689b53d78b19704000402010005c0843d05e0a7120580897a05c09a0c040404020100040004000e2014d5b543223eb8e67ea70c1884118122c77dfb0020140fc93cedded89186e5820100d80ad601c1a7d60295968302019072017e73000593b1a57301d802d602b2a5730200d603c2a7968303019683020191c17202720193c27202720393c1b2a57303009c73047eb1b5a4d901046393c2720472030593c1b2a573050073067307d603b1a4d60486028300027308d6057309d606c2a7d6079595927203730a96830301938cb2db6308b2a4730b00730c01720401730d938cb2db6308b2a4730e00730f01720401720593c5b2a4997203731000c5a77311d801d607b2a5731200968303019683020192c17207999999720173137314731593c27207720693c1b2a5731600731793c1b2a57318007319731ad608b2a4731b00d609997203731cd60a9596830201938cb2db63087208731d01720401720593c5b2a4720900c5a7d805d60ab1b5a4d9010a63d801d60cdb6308720a9591b1720c731e96830201938cb2720c731f0001732093b2e4c6720a0411732100b2e4c6720804117322007323d60bb2a5720900d60c7e720a05d60d9a73249c7325720cd60e9a73269c7327720c968304019372039a720a73289683020192c1720b99997201720d720e93c2720b720693c1b2a5720300720d93c1b2a59a7203732900720e732ad1ececec72027207720a95efecec72027207720a938cb2db6308b2a5732b00732c0001732d732e', 'creationHeight': 257321, 'assets': [], 'additionalRegisters': {}, 'transactionId': '423909c8e0f1354694bc7a74711cc41e10b577f36d1608e89454983ed389276e', 'index': 3, 'extension': {}}], 'dataInputs': [], 'outputs': [{'value': '1000000', 'ergoTree': '104e0402040004020400040204000400040204020404040404060406040004000408040404080e20ec7db8b46327614a657fe8f7391a9c264d86b7aca5832d52148ce1e38436dc6b0e20b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f30500040204000406040404020404040005020502040004020580dddb01050205d00f040205020402040204020404040004000502040404000402050201000e208557834f67bdc177ee9528d7d0faf33ef025666f1f45a70e7e57d32f327dcec40404050204000e2083759b1a3d080d043db81acd10e1a6cb5b6fff8815b32c0ccc3380a9691ad909040205020404050001000402040204000500040404000502050005020500050004000402040004020402040205d00f0100d829d601b2a5730000d602db63087201d603b27202730100d6048c720301d605db6308a7d606b27205730200d6078c720601d6089372047207d609b2a5730300d60adb63087209d60bb2720a730400d60c8c720b02d60d8c720602d60ee4c6a70411d60fb2720e730500d610e4c672090411d611b27210730600d612b27210730700d613b2720e730800d614b2720e730900d615b27210730a00d616b27210730b00d617b2720e730c00d618b2720a730d00d619b27205730e00d61ab2720e730f00d61b9683070193c17209c1a793c27209c2a7938c7218018c721901938c7218028c721902938c720b01720793b1720a731093b27210731100721ad61c7312d61ddb6903db6503fed61e8c720302d61f7313d62086028300027314d621b2a4731500d622db63087221d623b27222731600d6248c722301d62592b1a47317d626e4c672210411d627e4c67221050ed628b2a5731800d629db63087228d1ecec957208958f720c720dd806d62ab27202731900d62b8c722a02d62ce4c672010411d62de4c67201050ed62eb2a5731a00d62fb2db6308722e731b009683030196830601721b9372119a720f722b93721272139372159a7214731c937216721793720c99720d731d9683080193cbc27201721c93b2722c731e00721392b2722c731f0099721d732093722dc5a7720893721e7321938c722a01721f92722b73229683030193c2722ee4c6b2a4732300050e938c722f01722d938c722f027324d807d62ab27202732500d62b8c722a02d62cb2a4732600d62d8cb2db6308722c732701722002d62ee4c672010411d62fe4c67201050ed630b2db6308b2a57328007329009683030196830601721b9372119a720f99722b722d93721272139372157214937216721793720c720d96830a0193c17201c1722c93cbc27201721c93cbc2722c721c93b2722e732a00721393722ee4c6722c041193722fe4c6722c050e720893721e732b938c722a01721f93722b9a722d8cb2db6308b2a4732c01b2a4732d00732e000296830201938c723001722f938c723002732f7330959683020193722473317225d802d62ab2a4733200d62be4c6722a04119683020196830601721b9372129a7213733393721572149372169a7217721a8f7216721d93720c720d96830301938cb2db6308722a73340001733593b2722b733600997213733793b2722b7338007339733a959683030191720f7211722591b17222733bd807d62ab27222733c00d62b99720f7211d62c998c722a02722bd62d8c722a01d62eb27226733d00d62f90722c733ed6309683040196830201937224720793722e7213938cb2db6308b2a4733f0073400001722796830601721b93721199720f722b937212721393721599721495722f73417342937216721793720c9a720d95722f7343734496830201937204722d93721e722b9591722c7345d803d631b272297346017220d632b27229734700d633e4c672280411968303017230968302019683080193c17228c1722193c27228c27221938c7231017224938c7231028c722302938c723201722d938c723202722c93b27233734800722e93b27233734900b27226734a00938cb27202734b01722001722792722c734c7230734d', 'assets': [{'tokenId': '99272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e647', 'amount': '1'}, {'tokenId': '21038855e00a9e767ffbeb9bbc1f59c39555e9e11652dcb5a0f689b53d78b197', 'amount': '999999999988'}], 'additionalRegisters': {'R4': '1105b8e8e3820202188088b1e9a56080f0b252'}, 'creationHeight': 257330}, {'value': '1000000', 'ergoTree': '101d040004000e2099272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e6470402040204020404040404020500040005c80104060400040004020402040004000400040204000e240008cd02189359b825e96aa3c7af90c9958d85daf8f86358382db3306e024c5aeea1e8ec0580897a01010100040004000100d802d601b2a4730000d602c5a7d1ec9596830201938cb2db6308720173010001730293c5b2a47303007202d80cd603b2a5730400d604db63087203d605db6308a7d606b27205730500d607db6308b2a4730600d6089592b1720773078cb27207730800027309d6099a8c7206027208d60ae4c6a70411d60bb2720a730a00d60c8c720601d60d9d720b730bd60eb2a5730c00968302019683070193c17203c1a793c27203c2a7938cb27204730d00018cb27205730e000195917209720bd801d60fb27204730f0096830201938c720f01720c938c720f02997209720b93b17204731093e4c672030411720a93e4c67203050ee4c6a7050e93b2e4c6b2a57311000411731200999ab2e4c67201041173130099720b720d72089591b172047314d801d60fb2db6308720e7315009683040193c2720e731693c1720e7317938c720f01720c938c720f02720d731873199593c572017202938cb2db6308b2a5731a00731b0001e4c6a7050e731c', 'assets': [{'tokenId': '8557834f67bdc177ee9528d7d0faf33ef025666f1f45a70e7e57d32f327dcec4', 'amount': '1'}, {'tokenId': 'b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f3', 'amount': '49726030000'}], 'additionalRegisters': {'R4': '1101a0cda38502', 'R5': '0e2014d5b543223eb8e67ea70c1884118122c77dfb0020140fc93cedded89186e582'}, 'creationHeight': 257330}, {'value': '1000000', 'ergoTree': '102d0400040404020e20b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f3040004000e2099272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e6470404040604000402040205000402040004060400040605c8010400040001000402040004000e2021038855e00a9e767ffbeb9bbc1f59c39555e9e11652dcb5a0f689b53d78b197040004020100040606010004020400040004000402040204000404040004040404040404060100d807d601b2a4730000d602c5a7d603b2a5730100d604b2a4730200d6057303d606b2a5730400d607db6308a7d1ec9596830201938cb2db6308720173050001730693c5b2a47307007202d807d608e4c672030411d609b27208730800d60ab2e4c672040411730900d60bdb6308a7d60c9a8cb2db63087204730a00028cb2720b730b018602830002730c02d60ddb63087203d60eb2720d730d009683070193c17203c1a793c27203c2a793b47208730e730fb4e4c67201041173107311937209958f720a720c99720a9d720a7312720c938cb2720d731300018cb2720b73140001938c720e017205938c720e02720973159593c572017202d807d608db63087206d6097e8cb272077316000206d60ab5a4d9010a63d801d60cdb6308720a9591b1720c7317ed938cb2720c73180001731993b2e4c6720a0411731a00b2e4c6a70411731b00731cd60be4c6a70411d60cb2720b731d00d60db0720a731ed9010d42639a8c720d019d9c7e8cb2db63088c720d02731f0002067e720c067eb2720b73200006d60ee4c6720604119683070193c17206c1a793c27206c2a7938cb27208732100018cb272077322000195907209720d93b172087323d801d60fb27208732400ed938c720f017205927e8c720f0206997209720d93b4720e73257326b4720b7327732893b2720e73290099b2720b732a007eb1720a0593b2720e732b00720c732c', 'assets': [{'tokenId': '83759b1a3d080d043db81acd10e1a6cb5b6fff8815b32c0ccc3380a9691ad909', 'amount': '1'}, {'tokenId': 'b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f3', 'amount': '271230300'}], 'additionalRegisters': {'R4': '110480d30e0018b895d58202'}, 'creationHeight': 257330}, {'value': '1000000', 'ergoTree': '0008cd02189359b825e96aa3c7af90c9958d85daf8f86358382db3306e024c5aeea1e8ec', 'assets': [{'tokenId': 'b64a4682c11a4f02a50ba8f7d6587daebb93e55199f33a108c987ffb2cbd16f3', 'amount': '2739700'}], 'additionalRegisters': {}, 'creationHeight': 257330}, {'value': '95000000', 'ergoTree': '102f048084af5f04060400040205c0843d04040580897a010005000e2083759b1a3d080d043db81acd10e1a6cb5b6fff8815b32c0ccc3380a9691ad9090406040004000e2099272858f97ca9c1e6a313f1fb4c5e27912e0a7a5a76ceb065e52c3c11b6e6470404040004020100040805809bee020580897a0580897a040a05809bee02040c0580897a0100040004020400040004000e2021038855e00a9e767ffbeb9bbc1f59c39555e9e11652dcb5a0f689b53d78b19704000402010005c0843d05e0a7120580897a05c09a0c040404020100040004000e2014d5b543223eb8e67ea70c1884118122c77dfb0020140fc93cedded89186e5820100d80ad601c1a7d60295968302019072017e73000593b1a57301d802d602b2a5730200d603c2a7968303019683020191c17202720193c27202720393c1b2a57303009c73047eb1b5a4d901046393c2720472030593c1b2a573050073067307d603b1a4d60486028300027308d6057309d606c2a7d6079595927203730a96830301938cb2db6308b2a4730b00730c01720401730d938cb2db6308b2a4730e00730f01720401720593c5b2a4997203731000c5a77311d801d607b2a5731200968303019683020192c17207999999720173137314731593c27207720693c1b2a5731600731793c1b2a57318007319731ad608b2a4731b00d609997203731cd60a9596830201938cb2db63087208731d01720401720593c5b2a4720900c5a7d805d60ab1b5a4d9010a63d801d60cdb6308720a9591b1720c731e96830201938cb2720c731f0001732093b2e4c6720a0411732100b2e4c6720804117322007323d60bb2a5720900d60c7e720a05d60d9a73249c7325720cd60e9a73269c7327720c968304019372039a720a73289683020192c1720b99997201720d720e93c2720b720693c1b2a5720300720d93c1b2a59a7203732900720e732ad1ececec72027207720a95efecec72027207720a938cb2db6308b2a5732b00732c0001732d732e', 'assets': [], 'additionalRegisters': {}, 'creationHeight': 257330}, {'value': '3000000', 'ergoTree': '0008cd03d9d11f15c9564a310361e6c0edd34be6838d3cd811ec449f1bbce334599e0d01', 'assets': [], 'additionalRegisters': {}, 'creationHeight': 257330}, {'value': '1000000', 'ergoTree': '1005040004000e36100204900108cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304', 'assets': [], 'additionalRegisters': {}, 'creationHeight': 257330}]}

Error "There should be no duplicate inputs" when sending funds

A small whale got the error "There should be no duplicate inputs" when sending a big amount of ERGs.

Investigating the error turned out that BlockchainContextImpl.getUnspentBoxesFor with offset 20 returned some boxes that were already returned for offset 0. It looks like Ergo Explorer returned results are not disjoint:

Offset 0:

15 = {OutputInfo@28022} "class OutputInfo {\n    boxId: 12acc1cfcc6b9c22170fbeb13852dc866add291b92eed67e37cbda2a8fa29796\n    transactionId: 58d04ade811523d952a0bfc35fe77d34f9915b6c2e0fe430a960d40a9d2ee6be\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
16 = {OutputInfo@28023} "class OutputInfo {\n    boxId: bb3e14bf5a75fc52441caa281a6c84e92091d1d45af9f421838bc51e61e813d4\n    transactionId: 8ab3e4e42533aef2746515fa567a07ac31006891be365e51b9afb74e1d00692e\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
17 = {OutputInfo@28024} "class OutputInfo {\n    boxId: 7d8448ce645499ba6373d626fa264502dbfca329f108c0c31425b0176281fa9a\n    transactionId: 7424e7000a0d9ada39744cd11b43fdca43a009a2a3170fca5b7d4d729ea3c005\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
18 = {OutputInfo@28025} "class OutputInfo {\n    boxId: 6ea1f6c064dd8ad6a01dff9378a71ec0e8b4194e4d7d5f8e04b4150d27f14d85\n    transactionId: 513d31a418f8a24df2bae0b9a10aed859dc854c503e36f9e9660cc61b7ad86c9\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
19 = {OutputInfo@28026} "class OutputInfo {\n    boxId: 10fd280e5d00a4735a0bfedbd5608278b929a19246316b56b5028b8fcb37cf75\n    transactionId: d8e68b2b84aede4fd00ac21d60388bdb3539f2c1d554acf258a4f51d9c6d25ef\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"

Offset 20:

0 = {OutputInfo@28548} "class OutputInfo {\n    boxId: 98f5c7c486dea53653286a826d157ba3aa736686035b274d80177805c75cf322\n    transactionId: a4bd4e7f81dae310423b8b8bdcaa7e87338c18bbbb875800e11228638fd66bb5\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
1 = {OutputInfo@28549} "class OutputInfo {\n    boxId: 042d4325821ceeeb2e4e55c066c370ce76e40cbdccf758953a55dbb87f10c61b\n    transactionId: 6e093381ff743fb1232f72355bfbb1c24d7abf20e713e1a6dc58b77a34df7f83\n    blockId: 5f846f165b4e5a09b3d1feff6c8358c89ffc70df0e15fc3b3a97b90d17ee4861\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597744\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
2 = {OutputInfo@28550} "class OutputInfo {\n    boxId: 10fd280e5d00a4735a0bfedbd5608278b929a19246316b56b5028b8fcb37cf75\n    transactionId: d8e68b2b84aede4fd00ac21d60388bdb3539f2c1d554acf258a4f51d9c6d25ef\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
3 = {OutputInfo@28551} "class OutputInfo {\n    boxId: 12acc1cfcc6b9c22170fbeb13852dc866add291b92eed67e37cbda2a8fa29796\n    transactionId: 58d04ade811523d952a0bfc35fe77d34f9915b6c2e0fe430a960d40a9d2ee6be\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"
4 = {OutputInfo@28552} "class OutputInfo {\n    boxId: 6ea1f6c064dd8ad6a01dff9378a71ec0e8b4194e4d7d5f8e04b4150d27f14d85\n    transactionId: 513d31a418f8a24df2bae0b9a10aed859dc854c503e36f9e9660cc61b7ad86c9\n    blockId: 84d0dd691d73fe7e731e2d8449307617cd9a9a9b8c827697e2a7ce54635cbf8c\n    value: 10000000000\n    index: 0\n    creationHeight: 597741\n    settlementHeight: 597743\n    ergoTree: 0008cd03ebf2124bc8da317bf0152e416594df3662a5d6e947d75920c228b368bbca245b\n    address: 9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX\n    assets: []\n    spentTransactionId: null\n    mainChain: true\n}"

We can work around this behaviour by doing our own check in BoxOperations.loadTop and only add boxes that weren't already added. But doing so, we will miss some other boxes. Best would be a check of Explorer's code and sorting by a second column.

API used is transactions/boxes/byAddress/unspent/{id}
https://api.ergoplatform.com/api/v1/boxes/unspent/byAddress/9iFic39ctD5pngbHWX3WFipEJDRAZ2wyHircd8pCqGycHd7VrxX?offset=0&limit=20

Calling WalletApi.walletBoxesCollect throws an exception

I am trying to use the new WalletApi to get some boxes from my wallet.

I created the wallet service like this

// conf is of type ErgoToolConfig
val apiClient = new ApiClient(conf.getNode.getNodeApi.getApiUrl, "ApiKeyAuth", conf.getNode.getNodeApi.getApiKey)
val walletService = apiClient.createService(classOf[WalletApi])

Then I'm using it like this to get some amount of ERG from my wallet

val getWalletBoxesRequest = new BoxesRequestHolder().targetBalance(Parameters.OneErg)
val response = walletService.walletBoxesCollect(getWalletBoxesRequest).execute()

But that call throws the following error:

Exception in thread "main" java.lang.IllegalArgumentException: Non-body HTTP method cannot contain @Body.

After a little digging, I found that WalletApi.walletBoxesCollect queries /wallet/boxes/collect in the node's API, which is a POST endpoint.
image

However, I noticed that the appkit method that queries that endpoint has a @GET annotation for it
image

It seemed like the fix was as simple as changing the annotation from @GET to @POST, so I tried it locally. For simplicity's sake, I created a Java interface in my codebase,

public interface NewWalletApi {
    @Headers({
            "Content-Type:application/json"
    })
    @POST("wallet/boxes/collect")
    Call<List<WalletBox>> walletBoxesCollect(
            @retrofit2.http.Body BoxesRequestHolder body
    );
}

updated the wallet service creation to use the interface,

val walletService = apiClient.createService(classOf[NewWalletApi])

and tried executing a request again.

val getWalletBoxesRequest = new BoxesRequestHolder().targetBalance(Parameters.OneErg)
val response = walletService.walletBoxesCollect(getWalletBoxesRequest).execute()

This time, I just got a Bad Request back from the node, no further details.

So I went to the node's Swagger page to inspect that endpoint further (POST /wallet/boxes/collect), and soon learned some things about the expected request body.

image

  1. targetAssets is required and cannot be null.
  2. In the Swagger example, targetAssets is shown as a List of Lists (the BoxesRequestHolder Java model reflects this).
  3. Sending a request, via the Swagger page, following this suggested structure results in a 400 - Bad Request.

I tried out a few combinations

// empty list
{
    "targetAssets": []
    ...
}

// empty list with empty list
{
    "targetAssets": [[]]
    ...
}

// list of lists with "dummy" values
{
    "targetAssets": [["", 0]]
    ...
}

None worked. Until finally I tried this, and it worked!

{
    // empty object/map
    "targetAssets": {}
    ...
}

image

So, it looks like

  1. targetAssets cannot be null but it can be empty.
  2. Despite the Swagger example, targetAssets needs to be an object/map (where each key/value pair represent asset_id/amount), NOT a list of lists (array of arrays).

So, I tried updating the targetAssets property in the BoxesRequestHolder model to a HashMap<String, Long>, executed another request from my code using appkit, but then I got this error:

Note: to facilitate and speed up local testing of this, I created a new model NewBoxesRequestHolder, updated targetAssets as needed, and used it to build a request body instead of BoxesRequestHolder

Click to expand
public class NewBoxesRequestHolder {
    @SerializedName("targetAssets")
    private java.util.HashMap<String, Long> targetAssets = new HashMap<>();

    @SerializedName("targetBalance")
    private Long targetBalance = null;

    public NewBoxesRequestHolder targetAssets(java.util.HashMap<String, Long> targetAssets) {
        this.targetAssets = targetAssets;
        return this;
    }

    public NewBoxesRequestHolder targetBalance(Long targetBalance) {
        this.targetBalance = targetBalance;
        return this;
    }

    public java.util.HashMap<String, Long> getTargetAssets() {
        return targetAssets;
    }

    public void setTargetAssets(java.util.HashMap<String, Long> targetAssets) {
        this.targetAssets = targetAssets;
    }

    public Long getTargetBalance() {
        return targetBalance;
    }

    public void setTargetBalance(Long targetBalance) {
        this.targetBalance = targetBalance;
    }
}

Exception in thread "main" java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:39) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27) at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225) at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)

While I've figrued out how to send a valid request to POST /wallet/boxes/collect via the node's Swagger page, I have not yet managed to get it to work via appkit.

I'm still into it but this is as far as I've made it. If anyone has any useful insights into how to potentially resolve this issue, they'd be greatly appreciated!

Context variables not included in final singed transaction's toJson method

When we create a transaction with some inputs having context variables set via withContextVar, the following behaviour is observed:

  1. The method tx.toJson does not include context variables.
  2. When we finally broadcast the transaction, an error is encountered if the script uses context variables.

The above indicates that while the context variables are used in signing, they may not be included in the final transaction.

toJson method in SignedTransaction seems to have problems.

In case setting prettyPrint to true, "ergoTree" parameter of boxes in the transaction has a problem like the below example:

{ "ergoTree": "ErgoTree(0,WrappedArray(),Right(ConstantNode(SigmaProp(ProveDlog(ECPoint(4a186c,125e7c,...))),SSigmaProp)),80,[B@73d60e76)", }

Create EIP-3 compliant addresses

Current method Address.fromMnemonic is not EIP-3 compliant.

A new method Address.fromMnemonicEip3 needs to be created to support generation of EIP3 compliant first address.

UnsignedTransactionBuilderImpl move away from using DefaultBoxSelector

Currently, UnsignedTransactionBuilderImpl uses DefaultBoxSelector internally. The implementation has some major and some minor drawbacks that should be solved by changing the implementation:

  • DefaultBoxSelector is part of ergo-wallet dependency, bugfixes/enhancements/behaviour changes are hard to do
  • the current implementation expects the input boxes list in a prepared way: it does not accept "unnecessary" boxes as input, while it defines "unnecessary" in a very special way.

The second issue is especially restricting client code. For example, building the following transaction fails:

  • Input1: 1 ERG
  • Input2: 1 ERG
  • Output1: .5 ERG

=> Fails because second input is not needed. This is true, but when client code wants to build a transaction in this way, this should be accepted by the transaction builder and the unnecessary amount shoud be added to the changebox.

To add up to the confusion, it is even possible to add unnecessary boxes to the input list, some are accepted:

  • Input1: 1 ERG
  • Input2: 1 ERG + token1
  • Output1: .5ERG + token1

=> accepted

That means that every client code must all DefaultBoxSelector manually on an input box list to make sure the input boxes list satisfies the needs. This is done in appkit's BoxOperations loadTop method as well, which calls BoxSelectorsJavaHelpers.selectBoxes which is using DefaultBoxSelector internally, and must be done by client code on every transaction build.

Getting "Cost of transaction ErgoLikeTransactionTemplate( ... ) exceeds limit [...]" error

Getting error Cost of transaction ErgoLikeTransactionTemplate( ... ) exceeds limit 5062531

In appkit test node responses, I've set the maxBlockCost to be 5062531 as per the current mainnet (ref @kushti )

Full error here https://gist.github.com/scalahub/67a8293010428ea2bbfa2085690116fc

Here is the test that generates the error
https://github.com/scalahub/AppkitIssue/blob/main/src/test/scala/AppkitIssue.scala

The same transaction (plus few additional inputs) when created via the ergo node works fine:
https://explorer.ergoplatform.com/en/transactions/eab3020a702165b1328f720df99cee051b5c282b52fde563c291f97113bad1f3
We can verify that the addresses in the above tx and the test (AppkitIssue.scala) are the same

For reference, the scripts of the addresses correspond the code here:

ErgoScript: https://github.com/scalahub/OraclePool/blob/main/src/main/scala/oraclepool/v1a/Contracts.scala
Addresses: https://github.com/scalahub/OraclePool/blob/main/src/test/scala/oraclepool/v1a/AddressSpec.scala

Ability to add proxy connection

One of the most important goals of the mixer is anonymity, so it is important to be able to send requests through a proxy (Tor, ...).
This feature is currently implemented in the custom version of Appkit within the mixer project, and I'm trying to transfer these details to the official version of Appkit.
The following changes are made to the custom version:

java.security.NoSuchAlgorithmException: SecretKeyFactory PBKDF2WithHmacSHA512 implementation not found

The following error is thrown on older Android devices (< 8.0) when Address.fromMnemonic is called:

java.security.NoSuchAlgorithmException: SecretKeyFactory PBKDF2WithHmacSHA512 implementation not found
        at org.apache.harmony.security.fortress.Engine.notFound(Engine.java:190)
        at org.apache.harmony.security.fortress.Engine.getInstance(Engine.java:139)
        at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:108)
        at org.ergoplatform.wallet.mnemonic.Mnemonic$.toSeed(Mnemonic.scala:77)
        at org.ergoplatform.appkit.JavaHelpers$.seedToMasterKey(JavaHelpers.scala:354)
        at org.ergoplatform.appkit.JavaHelpers.seedToMasterKey(JavaHelpers.scala)
        at org.ergoplatform.appkit.Address.fromMnemonic(Address.java:135)

Algorithm is not included in Java 7. As you already ship with Bouncy castle, it should be easy to switch to its implementation that is available on all language levels. See here: https://stackoverflow.com/a/22621191/7487013

Allow "exact" transactions

From discord.
scalahub โ€” 05/10/2021
Can you modify appkit to accept zero fee when creating tx.. There is a situation where I need to add fee output manually and not via appkit.
Basically another method that allows user to specify the exact tx without appkit adding anything extra.

set parameter explorerUrl as an optional field

RestApiErgoClient(String nodeUrl, NetworkType networkType, String apiKey, String explorerUrl) {

According to the discussion in discord, I think it is better if explorerUrl to be optional so that Appkit method can work with Node and Explorer switch case defaultMainnetExplorerUrl or defaultTestnetExplorerUrl as long as specific Explorer is actually not needed.

Basic startup question using Javascript

I've completed the basic startup configuration and verified that my GraalVM is successfully installed. I'm using GraalVM CE 19.3.6, which has the openjdk 11.0.11. I'm using the current appkit 2.12-04.0.5 file which I installed from the published version. I'm on Ubuntu 20.0.4.

I have a simple script that I've cut down from FreezeCoin.js:

const Integer = Java.type("java.lang.Integer")
const Long = Java.type("java.lang.Long")
const Address = Java.type("org.ergoplatform.appkit.Address")
const RestApiErgoClient = Java.type("org.ergoplatform.appkit.RestApiErgoClient")
const ErgoClientException = Java.type("org.ergoplatform.appkit.ErgoClientException")
const ConstantsBuilder = Java.type("org.ergoplatform.appkit.ConstantsBuilder")
const ErgoToolConfig = Java.type("org.ergoplatform.appkit.config.ErgoToolConfig")
const Parameters = Java.type("org.ergoplatform.appkit.Parameters")

const conf = ErgoToolConfig.load("freeze_coin_config.json");

When I run this with the command line: js --jvm --vm.cp=target/ergo-appkit_2.12-4.0.5.jar examples/test.js

I get the following error:
java.lang.NoClassDefFoundError: com/google/gson/GsonBuilder at org.ergoplatform.appkit.config.ErgoToolConfig.load(ErgoToolConfig.java:53) at org.ergoplatform.appkit.config.ErgoToolConfig.load(ErgoToolConfig.java:67) at <js> :program(examples/test.js:10:557-590)

My config file is present in the directory. Any suggestions on how to resolve?

explorer.api not fitting current scheme, needs to be refreshed

I tried to execute some methods in AddressesApi without success:

  • addressesIdGet: Failed because FullAddressTransactions declares integers, but longs are coming
  • addressesIdTransactionsGet: Failed because it should return List<Transaction> but api call wraps the list

Looks like the wrappers need to be refreshed.

As a suggestion, maybe this should be extracted to an own lib. This way, it could get updated or changed without the need to update appkit itself.

Add way to persist SecretStorage to other places instead of File

SecretStorage/JsonSecretStorage are convinience classes operating on Files. It would be good if we have a way to persist the encrypted ExtendedSecretKey to other places than File. On Android, it is better to use a sqlite db for this, so a method returning the serialized end encrypted JsonSecretStorage as byte[] or String would be handy, and we would need of course the counterpart to create a SecretStorage from byte[] or String.

Until we have that, what would be the recommended work around to save the secrets to a db field? Easiest option would be to save the encrypted mnemonic and regenerate the secrets every time when needed, however, this does not feel solid.
Update: Found out secretstorage saves mnemonic anyway, so I do the same.

[planning] Appkit Roadmap

  • Commands processing layer implemented
    • Refactor Commands towards reusable components
    • Implement Commands layer API
    • Commands API is fully documented
  • blog-post is published (Introduction to Commands API)
    • blog-post draft
    • blog-post is reviewed and tags assigned
    • blog-post is converted to site page
    • marketing is planned
  • blog-post is published (Commands API: Under the Hood)

Prepare Appkit v5.0

Should be based on Sigma version currently used for v5.0 Ergo node release candidate.

Support primitive secrets in AppkitProvingInterpreter

Currently, AppKit supports primitive secrets for DHT, but only ExtendedSecretKey for Dlog.

Please note that in recent versions of ergo-wallet, SecretKey hierarchy was introduced, with support for both primitive and BIP-32 secrets. Thus AppkitProvingInterpreter constructor input can be simplified to just (JList[SecretKey)] (better to save old one also for the sake of backwards compatibility for sure)

Parameterise Usage Help of CliApplication

Problem

Currently the following places are hard coded:

val BaseDocUrl = "https://ergoplatform.github.io/ergo-tool/api"
Usage Syntax:\tergo-tool $name ${cmdParamSyntax}

Thus:

  • api url shown by HelpCmd command is incorrect for dex commands
  • usage syntax have incorrect name of executable

Solution

  • transform BaseDocUrl into abstract method def baseDocUrl: String in CmdDescriptor
  • ergoplatform/ergo-dex#7
  • introduce def launcher: String method to use in Usage Syntax above.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.