Chore: Automatic Testing and Documentation for Liquid (#1286)

* pin to newer version

* kick

* rename script and check prerequisites

* fail early and Dockerfile

* reduce threads again

* fix packages (not yet in DOCKERFILE)

* debug-log failed rpc-calls

* make funds available and fix address

* fix test

* fix test ... now explicitely ask to not confirm

* complete send test

* test single and multisig elem wallets

* testing also nested singlesig

* updates

* complete and fix multisig-tests

* fix tests

* ensure conn.json

* elements log in cirrus

* increase wait time for elements mining

* remove elm-log-stdout again

* start documenting

* increase timeout for last send

* log exception

* doc update

* small changes

* refactor Mining Testcode

* move images to dedicated folder

Co-authored-by: benk10 <ben.kaufman10@gmail.com>
This commit is contained in:
Kim Neunert 2021-08-03 14:52:18 +02:00 committed by GitHub
parent 6de2152f87
commit ed5d2ab756
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 664 additions and 113 deletions

View file

@ -12,14 +12,14 @@ prep_stuff_template: &PREP_STUFF_TEMPLATE
- cat pytest.ini | grep "addopts = " | cut -d'=' -f2 | sed 's/--/+/g' | tr '+' '\n' | grep bitcoin | cut -d' ' -f2
- cat tests/bitcoin_gitrev_pinned 2> /dev/null || true
- cat /etc/os-release | grep VERSION
populate_script: ./tests/install_bitcoind.sh binary
populate_script: ./tests/install_noded.sh binary
elementsd_installation_cache:
folder: ./tests/elements
fingerprint_script:
- cat pytest.ini | grep "addopts = " | cut -d'=' -f2 | sed 's/--/+/g' | tr '+' '\n' | grep elements | cut -d' ' -f2
- cat tests/elements_gitrev_pinned 2> /dev/null || true
- cat /etc/os-release | grep VERSION
populate_script: ./tests/install_bitcoind.sh --debug --elements compile
populate_script: ./tests/install_noded.sh --debug --elements compile
verify_script:
- echo " --> Version of python, virtualenv and pip3"
- python3 --version && virtualenv --version && pip3 --version

View file

@ -26,7 +26,7 @@ before_script:
- apt update
- apt install -y libusb-1.0-0-dev libudev-dev # usb-support in hidapi
# This doesn't get cached in gitlab but we don't need it anyway for now:
# - ./tests/install_bitcoind.sh --debug --elements compile
# - ./tests/install_noded.sh --debug --elements compile
- pip3 install --upgrade virtualenv
- virtualenv --python=python3 .env
- source .env/bin/activate

View file

@ -122,24 +122,24 @@ If you're stuck while installing/configuring Specter or you're looking for more
### Adding a new device
![](screenshots/devices.png)
![](./docs/images/README/devices.png)
![](screenshots/device_keys.png)
![](./docs/images/README/device_keys.png)
### Creating a new wallet
![](screenshots/wallets.png)
![](./docs/images/README/wallets.png)
![](screenshots/new_multisig.png)
![](./docs/images/README/new_multisig.png)
### Wallet interface
![](screenshots/transactions.png)
![](./docs/images/README/transactions.png)
![](screenshots/receive.png)
![](./docs/images/README/receive.png)
![](screenshots/send.png)
![](./docs/images/README/send.png)
### Configuration
![](screenshots/bitcoin-rpc.png)
![](./docs/images/README/bitcoin-rpc.png)

View file

@ -7,7 +7,8 @@
"spec_node_configured.js",
"spec_wallet_send.js",
"spec_wallet_utxo.js",
"spec_elm_wallet_send.js"
"spec_elm_single_segwit_wallet.js",
"spec_elm_multi_segwit_wallet.js"
],
"baseUrl": "http://localhost:25444"
}

View file

@ -0,0 +1,224 @@
describe('Operating with an elements multisig wallet', () => {
it('Creates an two elements multisig hot wallets (segwit/nested) both 2/3', () => {
cy.viewport(1200,660)
cy.visit('/')
cy.get('#node-switch-icon').click()
cy.get('#elements_node-select-node-form > .item > div').click()
// Delete Wallet if existing
cy.deleteWallet("Elm Multi Segwit Wallet")
cy.deleteWallet("Elm Multi Nested Wallet")
// Create the Hot Element Wallets
cy.addHotDevice("Hot Elements Device 2","elements")
cy.addHotDevice("Hot Elements Device 3","elements")
cy.addHotDevice("Hot Elements Device 4","elements")
// Create Segwit multisig wallet
cy.get('#btn_new_wallet').click()
cy.get('[href="./multisig/"]').click()
cy.get('#hot_elements_device_2').click()
cy.get('#hot_elements_device_3').click()
cy.get('#hot_elements_device_4').click()
cy.get('#submit-device').click()
cy.get('#wallet_name').type("Elm Multi Segwit Wallet")
cy.get(':nth-child(9) > .inline').clear()
// 2 of 2
cy.get(':nth-child(9) > .inline').type("2")
// submit
cy.get('#keysform > .centered').click()
// Cancel-button (no pdf download)
cy.get('#page_overlay_popup_cancel_button').click()
//Get some funds
cy.mine2wallet("elm")
// Create Nested multisig wallet
cy.get('#btn_new_wallet').click()
cy.get('[href="./multisig/"]').click()
cy.get('#hot_elements_device_2').click()
cy.get('#hot_elements_device_3').click()
cy.get('#hot_elements_device_4').click()
cy.get('#submit-device').click()
cy.get(':nth-child(1) > #type_nested_segwit_btn') // Nested!!
cy.get('#wallet_name').type("Elm Multi Nested Wallet")
cy.get(':nth-child(9) > .inline').clear()
// 2 of 2
cy.get(':nth-child(9) > .inline').type("2")
// submit
cy.get('#keysform > .centered').click()
// Cancel-button (no pdf download)
cy.get('#page_overlay_popup_cancel_button').click()
//Get some funds
cy.mine2wallet("elm")
})
it('Spending to a Confidential address from segwit', () => {
cy.viewport(1200,660)
cy.visit('/')
// spend the money again
cy.contains("Elm Multi Segwit Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("el1qqdsywea5scrn7t9q83fd540pw447h0uae30pdp82rzgkl7yzvjz6gra9ls8qu6sslw4s0ck48we06zhqd6kwjy2quh69zwxwn", "Burn address","1.5")
cy.get('#hot_elements_device_2_tx_sign_btn').click()
cy.get('#hot_elements_device_2_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#hot_elements_device_3_tx_sign_btn').click()
cy.get('#hot_elements_device_3_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
// cy.get('#broadcast_local_btn').click()
// There is a bug as the first device doesn't seem to have signed and so we can't send the tx just right from here
// 2 more clicks until to get to the send button
cy.get('#btn_send').click()
cy.get('.row > :nth-child(1) > .btn').click()
cy.get('#send_tx_btn').click()
cy.get('#broadcast_local_btn').click()
// gets redirected to "transactions"
cy.get('#fullbalance_amount')
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
// Workaround: Transaction does not disappear
cy.get('#btn_send').click()
// The "delete" button in the first psbt
cy.get('.row > :nth-child(2) > .btn').click()
})
it('Spending to a Unconfidential address from segwit', () => {
cy.viewport(1200,660)
cy.visit('/')
// spend the money again
cy.contains("Elm Multi Segwit Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("ert1q38la37ulxgc0uwt334he46eua7h8qagqnlm5phcqk7ntgv3x73cqjtr2fa", "unconf Burn address","1.5")
cy.get('#hot_elements_device_2_tx_sign_btn').click()
cy.get('#hot_elements_device_2_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#hot_elements_device_3_tx_sign_btn').click()
cy.get('#hot_elements_device_3_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
// cy.get('#broadcast_local_btn').click()
// There is a bug as the first device doesn't seem to have signed and so we can't send the tx just right from here
// 2 more clicks until to get to the send button
cy.get('#btn_send').click()
cy.get('.row > :nth-child(1) > .btn').click()
cy.get('#send_tx_btn').click()
cy.get('#broadcast_local_btn').click()
// gets redirected to "transactions"
cy.get('#fullbalance_amount')
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
// Workaround: Transaction does not disappear
// Strange bug, not needed here
// cy.get('#btn_send').click()
// The "delete" button in the first psbt
// cy.get('.row > :nth-child(2) > .btn').click()
})
it('Spending to a Confidential address from nested', () => {
cy.viewport(1200,660)
cy.visit('/')
// spend the money again
cy.contains("Elm Multi Nested Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("el1qqdsywea5scrn7t9q83fd540pw447h0uae30pdp82rzgkl7yzvjz6gra9ls8qu6sslw4s0ck48we06zhqd6kwjy2quh69zwxwn", "Burn address","1.5")
cy.get('#hot_elements_device_2_tx_sign_btn').click()
cy.get('#hot_elements_device_2_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#hot_elements_device_3_tx_sign_btn').click()
cy.get('#hot_elements_device_3_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
// cy.get('#broadcast_local_btn').click()
// There is a bug as the first device doesn't seem to have signed and so we can't send the tx just right from here
// 2 more clicks until to get to the send button
cy.get('#btn_send').click()
cy.get('.row > :nth-child(1) > .btn').click()
cy.get('#send_tx_btn').click()
cy.get('#broadcast_local_btn').click()
// gets redirected to "transactions"
cy.get('#fullbalance_amount')
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
// Workaround: Transaction does not disappear
cy.get('#btn_send').click()
// The "delete" button in the first psbt
cy.get('.row > :nth-child(2) > .btn').click()
})
it('Spending to a Unconfidential address from nested', () => {
cy.viewport(1200,660)
cy.visit('/')
// spend the money again
cy.contains("Elm Multi Nested Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("ert1q38la37ulxgc0uwt334he46eua7h8qagqnlm5phcqk7ntgv3x73cqjtr2fa", "unconf Burn address","1.5")
cy.get('#hot_elements_device_2_tx_sign_btn').click()
cy.get('#hot_elements_device_2_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#hot_elements_device_3_tx_sign_btn').click()
cy.get('#hot_elements_device_3_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
// cy.get('#broadcast_local_btn').click()
// There is a bug as the first device doesn't seem to have signed and so we can't send the tx just right from here
// 2 more clicks until to get to the send button
cy.get('#btn_send').click()
cy.get('.row > :nth-child(1) > .btn').click()
cy.get('#send_tx_btn').click()
cy.get('#broadcast_local_btn').click()
// gets redirected to "transactions"
cy.get('#fullbalance_amount', { timeout: 10000})
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
// Workaround: Transaction does not disappear
// Strange bug, not needed here
// cy.get('#btn_send').click()
// The "delete" button in the first psbt
// cy.get('.row > :nth-child(2) > .btn').click()
})
})

View file

@ -0,0 +1,114 @@
describe('Operating with an elements singlesig wallet', () => {
it('Creates a single sig elements hot wallet', () => {
cy.viewport(1300,660)
cy.visit('/')
cy.get('#node-switch-icon').click()
cy.get('#elements_node-select-node-form > .item > div').click()
// Delete Wallet if existing
cy.deleteWallet("Elm Single Segwit Hot Wallet")
cy.deleteWallet("Elm Single Nested Hot Wallet")
cy.addHotDevice("Hot Elements Device 1","elements")
// Segwit Wallet
cy.addHotWallet("Elm Single Segwit Hot Wallet","elements", "segwit")
// Nested Segwit Wallet
cy.addHotWallet("Elm Single Nested Hot Wallet","elements", "nested_segwit")
})
it('send confidential transaction from segwit', () => {
cy.viewport(1300,660)
cy.visit('/')
cy.contains("Elm Single Segwit Hot Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("el1qqdsywea5scrn7t9q83fd540pw447h0uae30pdp82rzgkl7yzvjz6gra9ls8qu6sslw4s0ck48we06zhqd6kwjy2quh69zwxwn", "Burn address","1.5")
cy.get('#hot_elements_device_1_tx_sign_btn').click()
cy.get('#hot_elements_device_1_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#broadcast_local_btn').click()
cy.get('#fullbalance_amount')
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
// Workaround: Transaction does not disappear
cy.get('#btn_send').click()
// The "delete" button in the first psbt
cy.get('.row > :nth-child(2) > .btn').click()
})
it('send unconfidential transaction from segwit', () => {
cy.viewport(1300,660)
cy.visit('/')
cy.contains("Elm Single Segwit Hot Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("ert1q38la37ulxgc0uwt334he46eua7h8qagqnlm5phcqk7ntgv3x73cqjtr2fa", "Burn address","1.5")
cy.get('#hot_elements_device_1_tx_sign_btn').click()
cy.get('#hot_elements_device_1_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#broadcast_local_btn').click()
cy.get('#fullbalance_amount')
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
})
it('send confidential transaction from nested segwit', () => {
cy.viewport(1300,660)
cy.visit('/')
cy.contains("Elm Single Nested Hot Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("el1qqdsywea5scrn7t9q83fd540pw447h0uae30pdp82rzgkl7yzvjz6gra9ls8qu6sslw4s0ck48we06zhqd6kwjy2quh69zwxwn", "Burn address","1.5")
cy.get('#hot_elements_device_1_tx_sign_btn').click()
cy.get('#hot_elements_device_1_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#broadcast_local_btn').click()
cy.get('#fullbalance_amount')
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
// Workaround: Transaction does not disappear
cy.get('#btn_send').click()
// The "delete" button in the first psbt
cy.get('.row > :nth-child(2) > .btn').click()
})
it('send unconfidential transaction from nested segwit', () => {
cy.viewport(1300,660)
cy.visit('/')
cy.contains("Elm Single Nested Hot Wallet").click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
expect(oldBalance).to.be.gte(1.5)
cy.createPsbt("ert1q38la37ulxgc0uwt334he46eua7h8qagqnlm5phcqk7ntgv3x73cqjtr2fa", "Burn address","1.5")
cy.get('#hot_elements_device_1_tx_sign_btn').click()
cy.get('#hot_elements_device_1_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#broadcast_local_btn').click()
cy.get('#fullbalance_amount')
.should(($div) => {
const newBalance = parseFloat($div.text())
expect(newBalance).to.be.lte(oldBalance - 1.5)
})
})
})
})

View file

@ -1,29 +0,0 @@
describe('Send transactions from elements wallets', () => {
it('Creates a single sig elements hot wallet on specter and send transaction', () => {
cy.viewport(1200,660)
cy.visit('/')
cy.get('#node-switch-icon').click()
cy.get('#elements_node-select-node-form > .item > div').click()
// empty so far
cy.addHotDevice("Hot Elements Device 1","elements")
//cy.addHotWallet("Test Elements Hot Wallet","elements")
cy.addHotWallet("Test Elements Hot Wallet 1","elements")
cy.get('#btn_send').click()
cy.get('#address_0').type("el1qqdsywea5scrn7t9q83fd540pw447h0uae30pdp82rzgkl7yzvjz6gra9ls8qu6sslw4s0ck48we06zhqd6kwjy2quh69zwxwn")
cy.get('#label_0').type("Burn address")
cy.get('#send_max_0').click()
cy.get('#create_psbt_btn').click()
// To be done:
/* cy.get('body').contains("Paste signed transaction")
cy.get('#hot_elements_device_1_tx_sign_btn').click()
cy.get('#hot_elements_device_1_hot_sign_btn').click()
cy.get('#hot_enter_passphrase__submit').click()
cy.get('#broadcast_local_btn').click()
cy.get('#fullbalance_amount')
.should(($div) => {
const n = parseFloat($div.text())
expect(n).to.be.equals(0)
}) */
})
})

View file

@ -20,15 +20,10 @@ describe('Node Configured', () => {
// Download PDF
// unfortunately this results in weird effects in cypress run
//cy.get('#pdf-wallet-download > img').click()
cy.task("btc:mine")
cy.wait(10000)
cy.get('#btn_continue').click()
cy.get('#btn_transactions').click()
cy.get('#fullbalance_amount')
.should(($div) => {
const n = parseFloat($div.text())
expect(n).to.be.gt(0).and.be.lte(50)
})
cy.mine2wallet("btc")
})
})

View file

@ -22,15 +22,9 @@ describe('Send transactions from bitcoin hotwallets', () => {
// unfortunately this results in weird effects in cypress run
//cy.get('#pdf-wallet-download > img').click()
cy.get('#btn_continue').click()
cy.get('#btn_transactions').click()
cy.task("btc:mine")
cy.wait(10000)
cy.get('#wallets-loading-done-refresh', { timeout: 10000 }).click()
cy.get('#fullbalance_amount')
.should(($div) => {
const n = parseFloat($div.text())
expect(n).to.be.gt(0).and.be.lte(50)
})
//get some funds
cy.mine2wallet("btc")
cy.get('#btn_send').click()
cy.get('#address_0').type("bcrt1qsj30deg0fgzckvlrn5757yk55yajqv6dqx0x7u")
cy.get('#label_0').type("Burn address")
@ -70,16 +64,10 @@ describe('Send transactions from bitcoin hotwallets', () => {
cy.get('body').contains("New wallet was created successfully!")
cy.get('#page_overlay_popup_cancel_button').click()
// Send transaction
cy.task("btc:mine")
cy.wait(10000)
cy.get('#btn_transactions').click()
cy.get('#wallets-loading-done-refresh', { timeout: 10000 }).click()
cy.reload()
cy.get('#fullbalance_amount')
.should(($div) => {
const n = parseFloat($div.text())
expect(n).to.be.gt(0).and.be.lte(50)
})
//get some funds
cy.mine2wallet("btc")
cy.get('#btn_send').click()
cy.get('#address_0').type("bcrt1qsj30deg0fgzckvlrn5757yk55yajqv6dqx0x7u")
cy.get('#label_0').type("Burn address")

View file

@ -56,9 +56,10 @@ Cypress.Commands.add("addDevice", (name) => {
Cypress.Commands.add("addHotDevice", (name, node_type) => {
// node_type is either elements or bitcoin
cy.get('body').then(($body) => {
cy.task("delete:elements-hotwallet")
//cy.task("delete:elements-hotwallet")
if ($body.text().includes(name)) {
cy.get('#devices_list > .item > div').click()
var refName = "#device_list_item_"+name.toLowerCase().replace(/ /g,"_")
cy.get(refName).click()
cy.get('#forget_device').click()
}
cy.get('#side-content').click()
@ -72,7 +73,10 @@ Cypress.Commands.add("addHotDevice", (name, node_type) => {
})
})
Cypress.Commands.add("addHotWallet", (name, node_type, single_multi) => {
Cypress.Commands.add("addHotWallet", (name, node_type, wallet_type, single_multi) => {
if (wallet_type == null) {
wallet_type = "segwit"
}
cy.get('body').then(($body) => {
if ($body.text().includes(name)) {
cy.contains(name).click()
@ -87,21 +91,66 @@ Cypress.Commands.add("addHotWallet", (name, node_type, single_multi) => {
cy.get('[href="./simple/"]').click()
cy.get('#hot_elements_device_1').click()
cy.get('#wallet_name').type(name)
if (wallet_type == "nested_segwit") {
cy.get(':nth-child(1) > #type_nested_segwit_btn').click()
}
// Create Wallet button:
cy.get('#keysform > .centered').click()
cy.get('body').contains("New wallet was created successfully!")
// // Download PDF
// // unfortunately this results in weird effects in cypress run
// //cy.get('#pdf-wallet-download > img').click()
cy.get('#btn_continue').click()
cy.get('#btn_transactions').click()
cy.task("elm:mine")
cy.wait(4000)
//Get some funds
cy.mine2wallet("elm")
})
})
Cypress.Commands.add("deleteWallet", (name) => {
cy.get('body').then(($body) => {
if ($body.text().includes(name)) {
cy.contains(name).click()
cy.get('#btn_settings').click()
cy.get('#advanced_settings_tab_btn').click()
cy.get('#delete_wallet').click()
// That does not seem to delete the wallet-file in elements, though
// So let's do that as well
cy.task("delete:elements-hotwallet")
}
})
})
Cypress.Commands.add("mine2wallet", (chain) => {
// Fund it and check the balance
cy.get('#btn_transactions').click()
cy.get('#fullbalance_amount').then(($div) => {
const oldBalance = parseFloat($div.text())
if (chain=="elm") {
cy.task("elm:mine")
} else if (chain=="btc") {
cy.task("btc:mine")
} else {
throw new Error("Unknown chain: " + chain)
}
cy.wait(10000)
cy.reload()
cy.get('#fullbalance_amount')
.should(($div) => {
const n = parseFloat($div.text())
expect(n).to.be.gt(0).and.be.lte(50)
})
const n = parseFloat($div.text())
expect(n).to.be.gt(oldBalance)
}
)
})
})
})
})
// Quick and easy way to fill out the send form and create a psbt
Cypress.Commands.add("createPsbt", (address, label="a_label", amount=0.01) => {
cy.get('#btn_send').click()
cy.get('#address_0').type(address)
cy.get('#label_0').type(label)
//cy.get('#send_max_0').click()
cy.get('#amount_0').type(amount)
cy.get('#create_psbt_btn').click()
})

View file

@ -5,7 +5,7 @@ from ubuntu:focal
# 3. cypress dependencies
RUN apt update && DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y \
libusb-1.0-0-dev libudev-dev python3 python3-virtualenv \
build-essential libtool autotools-dev automake pkg-config bsdmainutils libevent-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev bc \
build-essential libtool autotools-dev automake autoconf pkg-config bsdmainutils libevent-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev bc \
nodejs npm libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
# Stuff needed for Elements (compilation)

View file

@ -94,7 +94,7 @@ While installing, make sure you know the locations of where that stuff is instal
Now open and check the "Environment-variables" and check that the following lines are in there:
![](./runner_windows_envvars.png)
![](./images/continuous-integration_runner_windows_envvars.png)
## Runner

106
docs/elements.md Normal file
View file

@ -0,0 +1,106 @@
# Elements/Liquid Support
Since `v1.5.0`, Specter-Desktop has basic Elements/Liquid Support. You can run/connect your own elements/liquid-node, you can create Liquid-Hotwallets and even combine them to multisig-wallets. Multisig with three hotwallets is indeed not that useful, but it's a start. We're planning to also support different assets (and might even have that already) and also support for Jade and specter-DIY.
This document is a description on how to get started with elements/liquid. We'll first go into the details of setting up the node, mostly referring to external documents. Note that you have to checkout elements from source in order to get it running. The latest release `elements-0.18-1.12` is __not__ enough.
We'll first describe how to Compile elements, how to setup a liquid-node conveniently.
After that, we'll explain how to connect your Specter Desktop to that node, create wallets and receive some coins (via sideshift.ai). Signing transactions is nowhere different than in any other Hotwallet.
# Elements Compilation
Currently you have to checkout and compile elements yourself. You'll need to checkout the master-branch. If you want to be very sure that the collaboration works, you should checkout the exact commit which specter uses when doing automatic testing. You can see that commit in this [file](../tests/elements_gitrev_pinned) (currently `1ba24fe9b3cc3ad1166ed93a0969602d0c7898ff`).
You can checkout elements wherever you want as long as the `elementsd` and `elements-cli` will be available on the path or in the `tests/elements/src` folder. We assume here, you'll do the latter. If you have a ubuntu/debian-based linux, please check the easier way below before manually checking out:
```sh
cd tests
git clone https://github.com/ElementsProject/elements.git
cd elements
git checkout 1ba24fe9b3cc3ad1166ed93a0969602d0c7898ff # Use the commit from the file above
```
The rest is very system-specific and we're referring here to the documentation in liquid:
* [free-](https://github.com/ElementsProject/elements/blob/elements-0.18.1.12/doc/build-freebsd.md)/[net-](https://github.com/ElementsProject/elements/blob/elements-0.18.1.12/doc/build-netbsd.md)/[open-](https://github.com/ElementsProject/elements/blob/elements-0.18.1.12/doc/build-openbsd.md)BSD
* [OsX](https://github.com/ElementsProject/elements/blob/elements-0.18.1.12/doc/build-osx.md)
* [Unix/Linux](https://github.com/ElementsProject/elements/blob/elements-0.18.1.12/doc/build-unix.md)
* [Windows](https://github.com/ElementsProject/elements/blob/elements-0.18.1.12/doc/build-windows.md)
If you're running a Debian/Ubuntu-based Linux-System, you can most probably use the script which we're using internally to setup our test-system. This will include the clone/checkout above. So simply start, from the root-folder of the project:
```sh
./tests/install_noded.sh --elements compile
```
Make sure that this is successfull by checking these two files to be existent:
```sh
ls tests/elements/src/elements-cli tests/elements/src/elementsd
tests/elements/src/elements-cli tests/elements/src/elementsd
```
# Liquid Node
In order to validate Peg-Ins, you'll need RPC-access to your Bitcoin-Core node. I did this with a fullnode, it might also work with a pruned node (not tested, though).
First, we need to create the `elements.conf` file which is located in the `datadir`. If you don't specify the datadir at startup, the standard-directory is `<homefolder>/.elements/elements.conf`. Here is an example:
```
chain=liquidv1
mainchainrpchost=localhost
mainchainrpcport=8332
mainchainrpcuser=your-username
mainchainrpcpassword=your-user-password
rpcuser=liquiduser
rpcpassword=liquidpassword
```
We assume here, that you're running the liquid node on the same machine than the core-node, therefore `localhost`. Get the values for `mainchainrpcuser` and `mainchainrpcpassword` from your `bitcoin.conf`. You can choose `rpcuser` and `rpcpassword` as you like. You'll later need that in specter, to configure access to the elements-node, similiar than to the core-node.
After that, let's start the `elements-node`. We'll start it simply via the commandline in an extra-terminal. Transforming that to a proper service is beyond the scope of this tutorial.
```
tests/elements/src/elements/elementsd
```
A successfull startup will result in validating the blocks. Currently the blockheight for liquid is at about 1417550. So if it's running as expected, you should see blocks validating, lots of messages like this:
```
2021-07-26T15:31:09Z UpdateTip: new best=cbf3ce54912825928d51c8e49eb86a310b53d98c61da560bd9e95ee62e019cd0 height=1502 version=0x20000000 tx=1512 date='2018-09-28T10:38:59Z' progress=0.002000 cache=0.0MiB(13txo)
```
It took about 12 hours for a full-sync in my case on a Intel Quadcore Gen 6 3.50GHz.
# Liquid Configuration in Specter
You're probably familiar with this part. On the upper-left, click on the `two arrows -> connect a new node -> Connect existing node`. Here is a screenshots with the values fitting to the configuration above:
![](./images/elements/liquidconfig.png)
After clicking on `save`, the node will get selected. You see something like this in the upper left:
![](./images/elements/nav.png)
As you can your wallets disappeared but your devices did not. The shown wallets are now specific to the Node which has been selected. The node can be switched via the clicking on the two arrows.
![](./images/elements/nodechoose.png)
# Hotwallet-Creation
The process of creating a Liquid Hotwallet is very similiar to creating a Bitcoin-Core Hotwallet. First you need to create a Hotwallet-Device `Add new device -> Elements Core (hot wallet) -> Continue -> Enter Name -> Continue` (Don't forget to note the seed).
After that, you can directly create a single key wallet: `Create single key wallet -> Enter Name -> Create Wallet`. You can download the usual Backup Pdf.
So if you now get a receive-address, you have to choose between a Confidential and a Unconfidential address.
![](./images/elements/receive.png)
# Fund the wallet
There are many ways you can fund your wallet. Let's assume you have Bitcoin and want to receive LiquidBtc (LBTC). At [https://sideswap.io/peg-in-out/](https://sideswap.io/peg-in-out/) you can Peg-In some Btc as a service. At [https://sideshift.ai/](https://sideshift.ai/) you can [https://sideshift.ai/btc/liquid](swap) BTC agains LBTC (and [vice versa](https://sideshift.ai/liquid/btc)).
As an example, let'S choose sideshift.ai to swap some BTC to LBTC.
![](./images/elements/sideshift1.png) ![](./images/elements/sideshift2.png) ![](./images/elements/sideshift3.png) ![](./images/elements/sideshift4.png)
![](./images/elements/txs.png)

View file

Before

Width:  |  Height:  |  Size: 433 KiB

After

Width:  |  Height:  |  Size: 433 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 648 KiB

After

Width:  |  Height:  |  Size: 648 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 506 KiB

After

Width:  |  Height:  |  Size: 506 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 470 KiB

After

Width:  |  Height:  |  Size: 470 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 485 KiB

After

Width:  |  Height:  |  Size: 485 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 437 KiB

After

Width:  |  Height:  |  Size: 437 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 446 KiB

After

Width:  |  Height:  |  Size: 446 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 381 KiB

After

Width:  |  Height:  |  Size: 381 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Before After
Before After

View file

@ -2,13 +2,13 @@
When using Specter Desktop, there might be certain cases where you would want to make calls over the Tor network. The simplest way to setup Tor integration with Specter Desktop is to click on the Get Started button of the welcome page aand follow the setup wizard, which will install and configure Tor for you. You can also access it but going to Settings -> Tor tab, and clicking on Setup Tor.
<img width="956" alt="Screen Shot 2021-04-24 at 10 42 08" src="../screenshots/get-started-setup.png">
<img width="956" alt="Screen Shot 2021-04-24 at 10 42 08" src="./images/tor/get-started-setup.png">
<img width="1043" alt="Screen Shot 2021-04-24 at 10 43 42" src="../screenshots/tor-config-setup.png">
<img width="1043" alt="Screen Shot 2021-04-24 at 10 43 42" src="./images/tor/tor-config-setup.png">
These will take you through the one click setup process, just click "Setup Tor" and Specter will take care of installing, configuring and running the Tor daemon.
<img width="732" alt="Screen Shot 2021-04-24 at 10 42 17" src="../screenshots/setup-tor-daemon.png">
<img width="732" alt="Screen Shot 2021-04-24 at 10 42 17" src="./images/tor/setup-tor-daemon.png">
## Running Specter Desktop over a Tor hidden service
@ -22,7 +22,7 @@ Make sure authentication is enabled to avoid access to your Specter by random st
After setting up authentication, running the hidden service to remotely access specter is as easy as going to the Settings -> Tor tab, scrolling to the bottom and clicking the "Start" button under the "Tor Hidden Service" section.
<img width="755" alt="Screen Shot 2021-04-24 at 10 58 30" src="../screenshots/tor-hidden-service.png">
<img width="755" alt="Screen Shot 2021-04-24 at 10 58 30" src="./images/tor/tor-hidden-service.png">
## Manual Tor configurations
@ -45,7 +45,7 @@ If you're using Specter Desktop on a remote machine and would like to connect to
3. Enter your TOR URL
4. Switch on "Connect over TOR"
![](../screenshots/desktop-tor-preferences.gif)
![](./images/tor/desktop-tor-preferences.gif)
After saving, Specter will shutdown. Start it again and you should be able to connect to your remote Specter server.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

View file

@ -42,6 +42,12 @@ logger = logging.getLogger(__name__)
"--data-dir",
help="Specify a (maybe not yet existing) datadir. Works only with --nodocker. (Default is /tmp/bitcoind_plain_datadir)",
)
@click.option(
"--log-stdout",
is_flag=True,
default=False,
help="Will spit out logs on stdout if set",
)
@click.option(
"--mining/--no-mining",
default=True,
@ -79,6 +85,7 @@ def bitcoind(
nodocker,
docker_tag,
data_dir,
log_stdout,
mining,
mining_period,
reset,
@ -96,6 +103,7 @@ def bitcoind(
nodocker,
docker_tag,
data_dir,
log_stdout,
mining,
mining_period,
reset,
@ -114,6 +122,12 @@ def bitcoind(
"--data-dir",
help="Specify a (maybe not yet existing) datadir. Works only with --nodocker. (Default is /tmp/bitcoind_plain_datadir)",
)
@click.option(
"--log-stdout",
is_flag=True,
default=False,
help="Will spit out logs on stdout if set",
)
@click.option(
"--mining/--no-mining",
default=True,
@ -149,6 +163,7 @@ def bitcoind(
def elementsd(
quiet,
data_dir,
log_stdout,
mining,
mining_period,
reset,
@ -166,6 +181,7 @@ def elementsd(
True, # nodocker
None, # docker_tag
data_dir,
log_stdout,
mining,
mining_period,
reset,
@ -181,6 +197,7 @@ def noded(
nodocker,
docker_tag,
data_dir,
log_stdout,
mining,
mining_period,
reset,
@ -250,12 +267,14 @@ def noded(
cleanup_at_exit=True,
cleanup_hard=cleanuphard,
datadir=data_dir,
log_stdout=log_stdout,
)
elif node_impl == "elements":
my_node.start_elementsd(
cleanup_at_exit=True,
cleanup_hard=cleanuphard,
datadir=data_dir,
log_stdout=log_stdout,
)
except docker.errors.ImageNotFound:
echo(f"Image with tag {docker_tag} does not exist!")
@ -267,6 +286,8 @@ def noded(
if str(e).startswith("There is already a node running!"):
echo(f"{e} please reset via:")
echo(f"python3 -m cryptoadvance.specter {node_impl}d --reset")
else:
raise e
if not nodocker:
tags_of_image = [
image.split(":")[-1] for image in my_node.btcd_container.image.tags

View file

@ -161,6 +161,11 @@ class Device:
"single key" if wallet_type == "simple" else "multisig"
)
@property
def ref4name(self):
"""Device have names and sometimes you want a referenable string from that name. Is there a better name for that than ref4name ?"""
return self.name.lower().replace(" ", "_")
def __eq__(self, other):
if other is None:
return False

View file

@ -1,6 +1,7 @@
import os
import json
import logging
import pathlib
from flask_babel import lazy_gettext as _
from ..helpers import alias, load_jsons
@ -36,8 +37,7 @@ class DeviceManager:
if data_folder.startswith("~"):
data_folder = os.path.expanduser(data_folder)
# creating folders if they don't exist
if not os.path.isdir(data_folder):
os.mkdir(data_folder)
pathlib.Path(data_folder).mkdir(parents=True, exist_ok=True)
devices = {}
devices_files = load_jsons(self.data_folder, key="name")
for device_alias in devices_files:

View file

@ -32,6 +32,7 @@ class BitcoindPlainController(NodePlainController):
cleanup_at_exit=False,
cleanup_hard=False,
datadir=None,
log_stdout=False,
extra_args=[],
timeout=60,
):
@ -46,6 +47,7 @@ class BitcoindPlainController(NodePlainController):
cleanup_at_exit,
cleanup_hard,
datadir,
log_stdout,
extra_args,
timeout,
)

View file

@ -31,6 +31,7 @@ class BitcoindDockerController(NodeController):
cleanup_at_exit=False,
cleanup_hard=False,
datadir=None,
log_stdout=False,
extra_args=[],
timeout=60,
):
@ -38,6 +39,7 @@ class BitcoindDockerController(NodeController):
cleanup_at_exit,
cleanup_hard,
datadir,
log_stdout,
extra_args,
timeout,
)

View file

@ -31,6 +31,7 @@ class ElementsPlainController(NodePlainController):
cleanup_at_exit=False,
cleanup_hard=False,
datadir=None,
log_stdout=False,
extra_args=[],
timeout=60,
):
@ -43,6 +44,7 @@ class ElementsPlainController(NodePlainController):
cleanup_at_exit,
cleanup_hard,
datadir,
log_stdout,
extra_args,
timeout,
)
@ -56,6 +58,7 @@ class ElementsPlainController(NodePlainController):
rpcconn,
run_docker=True,
datadir=None,
log_stdout=False,
node_path="elementsd",
network="regtest", # Doesn't make sense here. For now, only "elreg" is supported
extra_args=[],
@ -75,10 +78,12 @@ class ElementsPlainController(NodePlainController):
)
btcd_cmd += " -rpcallowip=0.0.0.0/0 -rpcallowip=172.17.0.0/16 "
if not run_docker:
btcd_cmd += " -noprinttoconsole"
if not log_stdout:
btcd_cmd += " -noprinttoconsole"
if datadir == None:
datadir = tempfile.mkdtemp(prefix="bitcoind_datadir")
btcd_cmd += ' -datadir="{}" '.format(datadir)
print(f"extra_args={extra_args})")
if extra_args:
btcd_cmd += " {}".format(" ".join(extra_args))
logger.debug("constructed elementsd-command: %s", btcd_cmd)

View file

@ -127,6 +127,7 @@ class NodeController:
cleanup_at_exit=False,
cleanup_hard=False,
datadir=None,
log_stdout=False,
extra_args=[],
timeout=60,
):
@ -146,6 +147,7 @@ class NodeController:
cleanup_at_exit,
cleanup_hard=cleanup_hard,
datadir=datadir,
log_stdout=log_stdout,
extra_args=extra_args,
)
try:
@ -204,7 +206,12 @@ class NodeController:
return self.rpcconn.get_rpc()
def _start_node(
self, cleanup_at_exit, cleanup_hard=False, datadir=None, extra_args=[]
self,
cleanup_at_exit,
cleanup_hard=False,
datadir=None,
log_stdout=False,
extra_args=[],
):
raise Exception(f"This should not be used in the baseclass! self: {self}")
@ -226,7 +233,7 @@ class NodeController:
address = "el1qqf6tv4n8qp55qc04v4xts5snd9v5uurkry4vskef6lmecahj6c42jt9lnj0432287rs67z9vzq2zvuer036s5mahptwxgyd8k"
self.get_rpc().generatetoaddress(block_count, address)
def testcoin_faucet(self, address, amount=20):
def testcoin_faucet(self, address, amount=20, confirm_payment=True):
"""an easy way to get some testcoins"""
rpc = self.get_rpc()
try:
@ -256,6 +263,9 @@ class NodeController:
if btc_balance > amount:
break
default_rpc.sendtoaddress(address, amount)
if confirm_payment:
# confirm it
rpc.generatetoaddress(1, default_address)
@staticmethod
def check_node(rpcconn, raise_exception=False):
@ -324,6 +334,7 @@ class NodeController:
rpcconn,
run_docker=True,
datadir=None,
log_stdout=False,
node_path="bitcoind",
network="regtest",
extra_args=[],
@ -341,7 +352,8 @@ class NodeController:
)
btcd_cmd += " -rpcallowip=0.0.0.0/0 -rpcallowip=172.17.0.0/16 "
if not run_docker:
btcd_cmd += " -noprinttoconsole"
if not log_stdout:
btcd_cmd += " -noprinttoconsole"
if datadir == None:
datadir = tempfile.mkdtemp(prefix="bitcoind_datadir")
btcd_cmd += ' -datadir="{}" '.format(datadir)
@ -379,7 +391,12 @@ class NodePlainController(NodeController):
raise e
def _start_node(
self, cleanup_at_exit=True, cleanup_hard=False, datadir=None, extra_args=[]
self,
cleanup_at_exit=True,
cleanup_hard=False,
datadir=None,
log_stdout=False,
extra_args=[],
):
if datadir == None:
datadir = tempfile.mkdtemp(
@ -391,6 +408,7 @@ class NodePlainController(NodeController):
self.rpcconn,
run_docker=False,
datadir=datadir,
log_stdout=log_stdout,
node_path=self.node_path,
network=self.network,
extra_args=extra_args,

View file

@ -344,6 +344,7 @@ class BitcoinRPC:
)
self.r = r
if r.status_code != 200:
logger.debug(f"last call FAILED: {r.text} (raising RpcError)")
raise RpcError(
"Server responded with error code %d: %s" % (r.status_code, r.text), r
)

View file

@ -5,7 +5,7 @@
- device_alias: Active device alias.
#}
{% macro sidebar_device_list_item(device, device_alias) -%}
<a href="{{ url_for('devices_endpoint.device', device_alias=device.alias) }}" class="item {% if device_alias == device.alias %}active{% endif %}">
<a href="{{ url_for('devices_endpoint.device', device_alias=device.alias) }}" class="item {% if device_alias == device.alias %}active{% endif %}" id="device_list_item_{{ device.ref4name }}">
<img src="{{ url_for('static', filename='img/devices/' ~ device.icon) }}" width="22px">
<div>
{{ device.name }}<br>

View file

@ -12,12 +12,12 @@
<label>
<input type="radio" name="type" value="{{'sh-wsh' if wallet_type == 'multisig' else 'sh-wpkh'}}"
class="hidden" onchange="updateType(this.value);">
<div class="btn radio left">{{ _("Nested Segwit") }}</div>
<div class="btn radio left" id="type_nested_segwit_btn">{{ _("Nested Segwit") }}</div>
</label>
<label>
<input type="radio" name="type" value="{{'wsh' if wallet_type == 'multisig' else 'wpkh'}}" checked
class="hidden" onchange="updateType(this.value);">
<div class="btn radio right">{{ _("Segwit") }}</div>
class="hidden type_nested_segwit" onchange="updateType(this.value);">
<div class="btn radio right" id="type_nested_segwit_btn">{{ _("Segwit") }}</div>
</label>
</nav>

View file

@ -611,6 +611,7 @@ class Wallet:
self.full_utxo = sorted(utxo, key=lambda utxo: utxo["time"], reverse=True)
except Exception as e:
self.full_utxo = []
logger.exception(e)
raise SpecterError(f"Failed to load utxos, {e}")
def getdata(self):

View file

@ -0,0 +1 @@
1ba24fe9b3cc3ad1166ed93a0969602d0c7898ff

View file

@ -1,4 +1,6 @@
#!/bin/bash
# fail early
set -o pipefail
# chenage to the directory the script is located in
cd "$( dirname "${BASH_SOURCE[0]}" )/."
@ -63,7 +65,7 @@ function maybe_update {
else
echo " --> Pinned: $PINNED! Checkout needed!"
git fetch
git checkout $PINNED || exit 1
git checkout $PINNED
return 1
fi
fi
@ -113,9 +115,9 @@ function build_node_impl {
# optimizing for speed would use the maximum threads available:
#make -j$(nproc)
# but we're optimizing for mem-allocation. 1 thread is quite slow, let's try 4 (we have 4GB and need to find the sweet-spot)
make -j3
make -j2
cd ../.. #travis is sourcing this script
echo " --> Finished build bitcoind"
echo " --> Finished build $node_impl"
}
@ -129,8 +131,24 @@ function sub_help {
}
function check_compile_prerequisites {
REQUIRED_PKGS="build-essential libtool autotools-dev automake pkg-config bsdmainutils python3 autoconf"
REQUIRED_PKGS="$REQUIRED_PKGS libevent-dev libevent-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev bc nodejs npm libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb"
for REQUIRED_PKG in $REQUIRED_PKGS; do
PKG_OK=$(dpkg-query -W --showformat='${Status}\n' $REQUIRED_PKG|grep "install ok installed")
echo Checking for $REQUIRED_PKG: $PKG_OK
if [ "" = "$PKG_OK" ]; then
echo "No $REQUIRED_PKG. Setting up $REQUIRED_PKG."
echo "WARNING: THIS SHOULD NOT BE NECESSARY, PLEASE FIX!"
apt-get --yes install $REQUIRED_PKG
fi
done
}
function sub_compile {
START=$(date +%s.%N)
check_compile_prerequisites
node_impl=$1
echo " --> install_node.sh Start $(date) (compiling for $node_impl)"
echo " checkout ..."
@ -147,7 +165,7 @@ function sub_compile {
}
function sub_binary {
echo " --> install_bitcoind.sh Start $(date) (binary)"
echo " --> install_noded.sh Start $(date) (binary)"
START=$(date +%s.%N)
cd tests
# todo: Parametrize this
@ -165,7 +183,7 @@ function sub_binary {
echo " --> Finished installing bitcoind binary"
END=$(date +%s.%N)
DIFF=$(echo "$END - $START" | bc)
echo " --> install_bitcoind.sh End $(date) took $DIFF"
echo " --> install_noded.sh End $(date) took $DIFF"
}
function parse_and_execute() {

View file

@ -58,9 +58,26 @@ def test_rr_psbt_get(client, caplog):
assert data["result"] == []
def test_rr_psbt_post(client, caplog):
def test_rr_psbt_post(specter_regtest_configured, client, caplog):
caplog.set_level(logging.DEBUG)
""" testing the registration """
headers = {
"Authorization": "Basic "
+ base64.b64encode(bytes("someuser" + ":" + "somepassword", "ascii")).decode(
"ascii"
),
"Content-type": "application/json",
}
result = client.get(
"/api/v1alpha/wallets/a_simple_wallet/",
follow_redirects=True,
headers=headers,
)
# Why the heck does this fail?
# assert json.loads(result.data)["a_simple_wallet"]["info"]["balance"] > 0
result = client.post(
"/api/v1alpha/wallets/some_wallet/psbt",
data=dict(address="someaddress", amount=0.5),
@ -71,20 +88,13 @@ def test_rr_psbt_post(client, caplog):
"The server could not verify that you are authorized to access the URL requested."
)
headers = {
"Authorization": "Basic "
+ base64.b64encode(bytes("someuser" + ":" + "somepassword", "ascii")).decode(
"ascii"
),
"Content-type": "application/json",
}
result = client.post(
"/api/v1alpha/wallets/a_simple_wallet/psbt",
data="""
{
"recipients" : [
{
"address": "BCRT1qgc6h85z43g3ss2dl5zdrzrp3ef6av4neqcqhh8",
"address": "bcrt1qgc6h85z43g3ss2dl5zdrzrp3ef6av4neqcqhh8",
"amount": 0.1,
"unit": "btc",
"label": "someLabel"

View file

@ -101,7 +101,9 @@ def test_WalletImporter_integration(specter_regtest_configured, bitcoin_regtest)
dm: DeviceManager = someuser.device_manager
wallet = wallet_importer.create_wallet(someuser.wallet_manager)
# fund it with some coins
bitcoin_regtest.testcoin_faucet(address=wallet.getnewaddress())
bitcoin_regtest.testcoin_faucet(
address=wallet.getnewaddress(), confirm_payment=False
)
# Realize that the wallet has funds:
wallet.update()
wallet = someuser.wallet_manager.get_by_alias("another_simple_wallet")

View file

@ -133,14 +133,25 @@ function start_node {
if [ "$node_impl" = "bitcoind" ]; then
echo "--> Purging $BTCD_REGTEST_DATA_DIR"
rm -rf $BTCD_REGTEST_DATA_DIR
node_impl_abbrev=btcd
else
echo "--> Purging $ELMD_REGTEST_DATA_DIR"
rm -rf $ELMD_REGTEST_DATA_DIR
node_impl_abbrev=elmd
fi
fi
if [ "$CLEANUPHARD" = "true" ]; then
addopts="--cleanuphard"
fi
if [ "$node_impl" = "bitcoind" ]; then
if [ "$BTCLOGSTDOUT" = "true" ]; then
addopts="--log-stdout"
fi
else
if [ "$ELMLOGSTDOUT" = "true" ]; then
addopts="--log-stdout"
fi
fi
if [ "$DOCKER" != "true" ]; then
if [ "$node_impl" != "elementsd" ]; then # no docker for elementsd yet
addopts="$addopts --nodocker"
@ -154,9 +165,11 @@ function start_node {
elementsd_pid=$!
fi
while ! [ -f ./btcd-conn.json ] ; do
echo "--> Waiting for Starting ${node_impl_abbrev}-conn.json to be created ..."
while ! [ -f ./${node_impl_abbrev}-conn.json ] ; do
sleep 0.5
done
echo "--> ${node_impl_abbrev}-conn.json created ..."
}
@ -378,6 +391,10 @@ function parse_and_execute() {
DEBUG=--debug
shift
;;
--elm-log-stdout)
ELMLOGSTDOUT=true
shift
;;
--docker)
DOCKER=true
shift