Skip to content

Commit

Permalink
[Bitcoin] Fix TWBitcoinFeeCalculateFee (for JavaScript) (#3346)
Browse files Browse the repository at this point in the history
  • Loading branch information
lamafab authored Aug 2, 2023
1 parent b2749b2 commit ab65cfd
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ class TestBitcoinFee {

@Test
fun P2pkhCalculateFee() {
val satVb: Long = 10
val satVb = "10"
val tx = Numeric.hexStringToByteArray("02000000017be4e642bb278018ab12277de9427773ad1c5f5b1d164a157e0d99aa48dc1c1e000000006a473044022078eda020d4b86fcb3af78ef919912e6d79b81164dbbb0b0b96da6ac58a2de4b102201a5fd8d48734d5a02371c4b5ee551a69dca3842edbf577d863cf8ae9fdbbd4590121036666dd712e05a487916384bfcd5973eb53e8038eccbbf97f7eed775b87389536ffffffff01c0aff629010000001976a9145eaaa4f458f9158f86afcba08dd7448d27045e3d88ac00000000")
var fee = BitcoinFee.calculateFee(tx, satVb)
var fee = BitcoinFee.calculateFee(tx, satVb).toLong()

assertEquals(fee, 191 * satVb)
assertEquals(fee, 191 * satVb.toLong())
}

@Test
fun P2wpkhCalculateFee() {
val satVb: Long = 12
val satVb = "12"
val tx = Numeric.hexStringToByteArray("020000000111b9f62923af73e297abb69f749e7a1aa2735fbdfd32ac5f6aa89e5c96841c18000000006b483045022100df9ed0b662b759e68b89a42e7144cddf787782a7129d4df05642dd825930e6e6022051a08f577f11cc7390684bbad2951a6374072253ffcf2468d14035ed0d8cd6490121028d7dce6d72fb8f7af9566616c6436349c67ad379f2404dd66fe7085fe0fba28fffffffff01c0aff629010000001600140d0e1cec6c2babe8badde5e9b3dea667da90036d00000000")
var fee = BitcoinFee.calculateFee(tx, satVb)
var fee = BitcoinFee.calculateFee(tx, satVb).toLong()

assertEquals(fee, 189 * satVb)
assertEquals(fee, 189 * satVb.toLong())
}

@Test
Expand All @@ -38,10 +38,10 @@ class TestBitcoinFee {
// Size 235 Bytes
// Weight 610
fun Brc20TransferCommitCalculateFee() {
val satVb: Long = 19
val satVb = "19"
val tx = Numeric.hexStringToByteArray("02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000")
var fee = BitcoinFee.calculateFee(tx, satVb)
var fee = BitcoinFee.calculateFee(tx, satVb).toLong()

assertEquals(fee, 153 * satVb) // 153 = ceil(610/4)
assertEquals(fee, 153 * satVb.toLong()) // 153 = ceil(610/4)
}
}
8 changes: 7 additions & 1 deletion include/TrustWalletCore/TWBitcoinFee.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@
#pragma once

#include "TWData.h"
#include "TWString.h"

TW_EXTERN_C_BEGIN

TW_EXPORT_CLASS
struct TWBitcoinFee;

/// Calculates the fee of any Bitcoin transaction.
///
/// \param data: the signed transaction in its final form.
/// \param satVb: the satoshis per vbyte amount. The passed on string is interpreted as a unit64_t.
/// \returns the fee denominated in satoshis or nullptr if the transaction failed to be decoded.
TW_EXPORT_STATIC_METHOD
uint64_t TWBitcoinFeeCalculateFee(TWData* _Nonnull data, uint64_t satVb);
TWString* _Nullable TWBitcoinFeeCalculateFee(TWData* _Nonnull data, TWString* _Nonnull satVb);

TW_EXTERN_C_END
2 changes: 1 addition & 1 deletion samples/kmp/shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("com.trustwallet:wallet-core-kotlin:3.2.7")
implementation("com.trustwallet:wallet-core-kotlin:3.2.8")
}
}
val commonTest by getting {
Expand Down
11 changes: 6 additions & 5 deletions src/interface/TWBitcoinFee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

#include <TrustWalletCore/TWBitcoinFee.h>
#include "Bitcoin/Transaction.h"
#include "Data.h"

uint64_t TWBitcoinFeeCalculateFee(TWData* _Nonnull data, uint64_t satVb) {
TWString* _Nullable TWBitcoinFeeCalculateFee(TWData* _Nonnull data, TWString* _Nonnull satVb) {
auto* encoded = reinterpret_cast<const TW::Data*>(data);
auto fee = TW::Bitcoin::Transaction::calculateFee(*encoded, satVb);
const std::string& satVbStr = *reinterpret_cast<const std::string*>(satVb);
uint64_t satVbInt = std::stoull(satVbStr);
auto fee = TW::Bitcoin::Transaction::calculateFee(*encoded, satVbInt);
if (!fee) {
return 0;
return nullptr;
}

return fee.value();
return TWStringCreateWithUTF8Bytes(std::to_string(*fee).c_str());
}
21 changes: 12 additions & 9 deletions swift/Tests/Blockchains/BitcoinTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -473,17 +473,19 @@ class BitcoinTransactionSignerTests: XCTestCase {
}

func testBitcoinP2pkhCalculateFee() throws {
let satVb: UInt64 = 10
let satVb = "10"
let tx = Data(hexString: "02000000017be4e642bb278018ab12277de9427773ad1c5f5b1d164a157e0d99aa48dc1c1e000000006a473044022078eda020d4b86fcb3af78ef919912e6d79b81164dbbb0b0b96da6ac58a2de4b102201a5fd8d48734d5a02371c4b5ee551a69dca3842edbf577d863cf8ae9fdbbd4590121036666dd712e05a487916384bfcd5973eb53e8038eccbbf97f7eed775b87389536ffffffff01c0aff629010000001976a9145eaaa4f458f9158f86afcba08dd7448d27045e3d88ac00000000")!
let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)
XCTAssertEqual(fee, 191 * satVb)
let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)!
let feeInt = UInt64(fee)!
XCTAssertEqual(feeInt, 191 * 10)
}

func testBitcoinP2wpkhCalculateFee() throws {
let satVb: UInt64 = 12
let satVb = "12"
let tx = Data(hexString: "020000000111b9f62923af73e297abb69f749e7a1aa2735fbdfd32ac5f6aa89e5c96841c18000000006b483045022100df9ed0b662b759e68b89a42e7144cddf787782a7129d4df05642dd825930e6e6022051a08f577f11cc7390684bbad2951a6374072253ffcf2468d14035ed0d8cd6490121028d7dce6d72fb8f7af9566616c6436349c67ad379f2404dd66fe7085fe0fba28fffffffff01c0aff629010000001600140d0e1cec6c2babe8badde5e9b3dea667da90036d00000000")!
let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)
XCTAssertEqual(fee, 189 * satVb)
let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)!
let feeInt = UInt64(fee)!
XCTAssertEqual(feeInt, 189 * 12)
}

// Metadata can be observed live on:
Expand All @@ -493,10 +495,11 @@ class BitcoinTransactionSignerTests: XCTestCase {
// Size 235 Bytes
// Weight 610
func testBitcoinBrc20TransferCommitCalculateFee() throws {
let satVb: UInt64 = 19
let satVb = "19"
let tx = Data(hexString: "02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000")!
let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)
XCTAssertEqual(fee, 153 * satVb) // 153 = ceil(610/4)
let fee = BitcoinFee.calculateFee(data: tx, satVb: satVb)!
let feeInt = UInt64(fee);
XCTAssertEqual(feeInt, 153 * 19) // 153 = ceil(610/4)
}
}

Expand Down
18 changes: 9 additions & 9 deletions tests/chains/Bitcoin/TWBitcoinFeeTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@
namespace TW::Bitcoin {

TEST(TWBitcoinFee, P2pkhFee) {
auto satVb = 10;
const auto satVb = STRING("10");
auto data = DATA("02000000017be4e642bb278018ab12277de9427773ad1c5f5b1d164a157e0d99aa48dc1c1e000000006a473044022078eda020d4b86fcb3af78ef919912e6d79b81164dbbb0b0b96da6ac58a2de4b102201a5fd8d48734d5a02371c4b5ee551a69dca3842edbf577d863cf8ae9fdbbd4590121036666dd712e05a487916384bfcd5973eb53e8038eccbbf97f7eed775b87389536ffffffff01c0aff629010000001976a9145eaaa4f458f9158f86afcba08dd7448d27045e3d88ac00000000");
auto fee = TWBitcoinFeeCalculateFee(data.get(), satVb);
ASSERT_EQ(fee, 191UL * satVb);
const auto fee = WRAPS(TWBitcoinFeeCalculateFee(data.get(), satVb.get()));
assertStringsEqual(fee, std::to_string(191UL * 10).c_str());
}

TEST(TWBitcoinFee, P2wpkhFee) {
auto satVb = 12;
const auto satVb = STRING("12");
auto data = DATA("020000000111b9f62923af73e297abb69f749e7a1aa2735fbdfd32ac5f6aa89e5c96841c18000000006b483045022100df9ed0b662b759e68b89a42e7144cddf787782a7129d4df05642dd825930e6e6022051a08f577f11cc7390684bbad2951a6374072253ffcf2468d14035ed0d8cd6490121028d7dce6d72fb8f7af9566616c6436349c67ad379f2404dd66fe7085fe0fba28fffffffff01c0aff629010000001600140d0e1cec6c2babe8badde5e9b3dea667da90036d00000000");
auto fee = TWBitcoinFeeCalculateFee(data.get(), satVb);
ASSERT_EQ(fee, 189UL * satVb);
const auto fee = WRAPS(TWBitcoinFeeCalculateFee(data.get(), satVb.get()));
assertStringsEqual(fee, std::to_string(189UL * 12).c_str());
}

// Metadata can be observed live on:
Expand All @@ -31,10 +31,10 @@ TEST(TWBitcoinFee, P2wpkhFee) {
// Size 235 Bytes
// Weight 610
TEST(TWBitcoinFee, BRC20TransferCommitFee) {
auto satVb = 19;
const auto satVb = STRING("19");
auto data = DATA("02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000");
auto fee = TWBitcoinFeeCalculateFee(data.get(), satVb);
ASSERT_EQ(fee, 153UL * satVb); // 153 = ceil(610/4)
const auto fee = WRAPS(TWBitcoinFeeCalculateFee(data.get(), satVb.get()));
assertStringsEqual(fee, std::to_string(153UL * 19).c_str()); // 153 = ceil(610/4)
}

} // namespace TW::Bitcoin
10 changes: 10 additions & 0 deletions wasm/tests/Blockchain/Bitcoin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,14 @@ describe("Bitcoin", () => {
assert.isTrue(outputHex.endsWith("5b0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800377b2270223a226272632d3230222c226f70223a227472616e73666572222c227469636b223a226f616466222c22616d74223a223230227d6821c00f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000"))
assert.equal(output.transactionId, "7046dc2689a27e143ea2ad1039710885147e9485ab6453fa7e87464aa7dd3eca");
});

it("test Bitcoin calculate BRC20 Commit fee", () => {
const { BitcoinFee, HexCoding } = globalThis.core;

const rawTx = HexCoding.decode("02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000");
const satVb = "19";

const fee = BitcoinFee.calculateFee(rawTx, satVb);
assert.equal(fee, "2907") // 19*153
});
});

0 comments on commit ab65cfd

Please sign in to comment.