Skip to content

Commit e8a6f15

Browse files
committed
Handled cashaddr prefixes in encodeUri
1 parent 2306291 commit e8a6f15

File tree

5 files changed

+238
-5
lines changed

5 files changed

+238
-5
lines changed

src/common/plugin/CurrencyTools.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,20 @@ export function makeCurrencyTools(
169169
obj: EdgeEncodeUri & EncodeUriMetadata,
170170
_customTokens?: EdgeMetaToken[]
171171
): Promise<string> {
172-
const { publicAddress } = obj
172+
let publicAddress = obj.publicAddress
173173
if (publicAddress === '') {
174174
throw new Error('InvalidPublicAddressError')
175175
}
176176

177+
// Remove any cashaddr prefixes from the public address if they exist.
178+
if (
179+
coinInfo.prefixes.cashaddr?.some(prefix =>
180+
publicAddress.startsWith(`${prefix}:`)
181+
) === true
182+
) {
183+
publicAddress = publicAddress.split(':')[1]
184+
}
185+
177186
// TODO: validate network address
178187

179188
const query: string[] = []

test/common/plugin/CurrencyPlugin.fixtures/currencies/bitcoincash.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,31 @@ export const bitcoincash: FixtureType = {
275275
{ publicAddress: '1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu' },
276276
'1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu'
277277
],
278+
'cashaddr prefixed address only': [
279+
{
280+
publicAddress: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a'
281+
},
282+
'qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a'
283+
],
284+
'cashaddr prefixed address with amount': [
285+
{
286+
publicAddress: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
287+
nativeAmount: '123456780000'
288+
},
289+
'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?amount=1234.5678'
290+
],
291+
'cashaddr prefixed address with amount and metadata': [
292+
{
293+
publicAddress: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
294+
nativeAmount: '123456780000',
295+
currencyCode: 'BCH',
296+
metadata: {
297+
name: 'Johnny BitcoinCash',
298+
notes: 'Hello World, I miss you !'
299+
}
300+
},
301+
'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?amount=1234.5678&label=Johnny%20BitcoinCash&message=Hello%20World,%20I%20miss%20you%20!'
302+
],
278303
'address & amount': [
279304
{
280305
publicAddress: 'qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import { airbitzSeeds, FixtureType, key, mnemonics } from '../common'
2+
3+
export const ecash: FixtureType = {
4+
pluginId: 'ecash',
5+
WALLET_TYPE: 'wallet:ecash',
6+
WALLET_FORMAT: 'bip44',
7+
'Test Currency code': 'XEC',
8+
key,
9+
xpub:
10+
'xpub6BrtJ1DTaX6hhhGgKiZ4M4LyGzxUBdQmQw6HW7e53x44C9BhiM5wJk5D6h8BJH1suQN9YHei2A9Jr4E4hDBCszKU4xdUZC3dZu1YP2TnW7q',
11+
'invalid key name': {
12+
id: 'unknown',
13+
type: 'wallet:ecash',
14+
keys: {
15+
ecashKeyz: '12345678abcd',
16+
format: 'bip44'
17+
}
18+
},
19+
'invalid wallet type': {
20+
id: 'unknown',
21+
type: 'shitcoin',
22+
keys: { ecashKeyz: '12345678abcd' }
23+
},
24+
importKey: {
25+
validKeys: [...mnemonics],
26+
invalidKeys: [
27+
...airbitzSeeds.map(seed => seed.slice(1)),
28+
...mnemonics.map(mnemonic => mnemonic.split(' ').slice(1).join(' ')),
29+
'bunch of garbly gook !@#$%^&*()'
30+
],
31+
unsupportedKeys: airbitzSeeds
32+
},
33+
parseUri: {
34+
'address only': [
35+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
36+
{
37+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
38+
metadata: {}
39+
}
40+
],
41+
'address only2': [
42+
'ecash:qrxcfwvkxumlnq28we8e9v0hjes45nw34gjjtvmlsw',
43+
{
44+
publicAddress: 'qrxcfwvkxumlnq28we8e9v0hjes45nw34gjjtvmlsw',
45+
metadata: {}
46+
}
47+
],
48+
'uri address': [
49+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
50+
{
51+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
52+
metadata: {}
53+
}
54+
],
55+
'uri address with amount': [
56+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=12345678.9',
57+
{
58+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
59+
metadata: {},
60+
nativeAmount: '1234567890',
61+
currencyCode: 'XEC'
62+
}
63+
],
64+
'uri address with amount & label': [
65+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=12345678.9&label=Johnny%20eCash',
66+
{
67+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
68+
metadata: {
69+
name: 'Johnny eCash'
70+
},
71+
nativeAmount: '1234567890',
72+
currencyCode: 'XEC'
73+
}
74+
],
75+
'uri address with amount, label & message': [
76+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=12345678.9&label=Johnny%20eCash&message=Hello%20World,%20I%20miss%20you%20!',
77+
{
78+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
79+
metadata: {
80+
name: 'Johnny eCash',
81+
notes: 'Hello World, I miss you !'
82+
},
83+
nativeAmount: '1234567890',
84+
currencyCode: 'XEC'
85+
}
86+
]
87+
},
88+
encodeUri: {
89+
'address only': [
90+
{ publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna' },
91+
'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna'
92+
],
93+
// Test cashaddr prefix removal - address only (should strip prefix and return same as non-prefixed)
94+
'cashaddr prefixed address only': [
95+
{ publicAddress: 'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna' },
96+
'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna'
97+
],
98+
// Test cashaddr prefix removal - with amount (should strip prefix and return same as non-prefixed)
99+
'cashaddr prefixed address with amount': [
100+
{
101+
publicAddress: 'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
102+
nativeAmount: '123456780'
103+
},
104+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=1234567.8'
105+
],
106+
// Test cashaddr prefix removal - with amount and metadata (should strip prefix and return same as non-prefixed)
107+
'cashaddr prefixed address with amount and metadata': [
108+
{
109+
publicAddress: 'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
110+
nativeAmount: '123456780',
111+
currencyCode: 'XEC',
112+
metadata: {
113+
name: 'Johnny eCash',
114+
notes: 'Hello World, I miss you !'
115+
}
116+
},
117+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=1234567.8&label=Johnny%20eCash&message=Hello%20World,%20I%20miss%20you%20!'
118+
],
119+
'address & amount': [
120+
{
121+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
122+
nativeAmount: '123456780'
123+
},
124+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=1234567.8'
125+
],
126+
'address, amount, and label': [
127+
{
128+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
129+
nativeAmount: '123456780',
130+
currencyCode: 'XEC',
131+
metadata: {
132+
name: 'Johnny eCash'
133+
}
134+
},
135+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=1234567.8&label=Johnny%20eCash'
136+
],
137+
'address, amount, label, & message': [
138+
{
139+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
140+
nativeAmount: '123456780',
141+
currencyCode: 'XEC',
142+
metadata: {
143+
name: 'Johnny eCash',
144+
notes: 'Hello World, I miss you !'
145+
}
146+
},
147+
'ecash:qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna?amount=1234567.8&label=Johnny%20eCash&message=Hello%20World,%20I%20miss%20you%20!'
148+
],
149+
'invalid currencyCode': [
150+
{
151+
publicAddress: 'qpmq6uvs4sktft22lhlmsqpfr53hq03snc0s4nlwna',
152+
nativeAmount: '123456780',
153+
currencyCode: 'INVALID',
154+
metadata: {
155+
name: 'Johnny eCash',
156+
notes: 'Hello World, I miss you !'
157+
}
158+
}
159+
]
160+
}
161+
}

test/common/plugin/CurrencyPlugin.fixtures/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { bitcoin } from './currencies/bitcoin'
33
import { bitcoincash } from './currencies/bitcoincash'
44
import { bitcoinsv } from './currencies/bitcoinsv'
55
import { digibyte } from './currencies/digibyte'
6+
import { ecash } from './currencies/ecash'
67
import { feathercoin } from './currencies/feathercoin'
78
import { groestlcoin } from './currencies/groestlcoin'
89
import { litecoin } from './currencies/litecoin'
@@ -14,6 +15,7 @@ export const fixtures: FixtureType[] = [
1415
bitcoincash,
1516
bitcoinsv,
1617
digibyte,
18+
ecash,
1719
feathercoin,
1820
groestlcoin,
1921
litecoin,

test/common/plugin/CurrencyPlugin.spec.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
EdgeCorePluginOptions,
55
EdgeCurrencyPlugin,
66
EdgeCurrencyTools,
7-
JsonObject,
87
makeFakeIo
98
} from 'edge-core-js'
109
import { before, describe, it } from 'mocha'
@@ -20,7 +19,6 @@ describe('currencyPlugins.spec', () => {
2019
const WALLET_FORMAT = fixture.WALLET_FORMAT
2120
const keyName = WALLET_TYPE.split('wallet:')[1].split('-')[0] + 'Key'
2221

23-
let keys: JsonObject
2422
let tools: EdgeCurrencyTools
2523

2624
const fakeIo = makeFakeIo()
@@ -63,6 +61,12 @@ describe('currencyPlugins.spec', () => {
6361
})
6462

6563
describe(`createPrivateKey for Wallet type ${WALLET_TYPE}`, function () {
64+
before('Plugin', async function () {
65+
if (tools == null) {
66+
tools = await plugin.makeCurrencyTools()
67+
}
68+
})
69+
6670
it('Test Currency code', function () {
6771
assert.equal(
6872
plugin.currencyInfo.currencyCode,
@@ -71,7 +75,7 @@ describe('currencyPlugins.spec', () => {
7175
})
7276

7377
it('Create valid key', async function () {
74-
keys = await tools.createPrivateKey(WALLET_TYPE)
78+
const keys = await tools.createPrivateKey(WALLET_TYPE)
7579
assert.isOk(keys)
7680
assert.equal(typeof keys[keyName], 'string')
7781
const length = keys[keyName].split(' ').length
@@ -80,6 +84,12 @@ describe('currencyPlugins.spec', () => {
8084
})
8185

8286
describe(`importPrivateKey for Wallet type ${WALLET_TYPE}`, function () {
87+
before('Plugin', async function () {
88+
if (tools == null) {
89+
tools = await plugin.makeCurrencyTools()
90+
}
91+
})
92+
8393
it('Import valid keys', async function () {
8494
// assert that the function is implemented
8595
if (tools.importPrivateKey == null) return
@@ -116,7 +126,14 @@ describe('currencyPlugins.spec', () => {
116126

117127
describe(`derivePublicKey for Wallet type ${WALLET_TYPE}`, function () {
118128
this.timeout(10000)
129+
before('Plugin', async function () {
130+
if (tools == null) {
131+
tools = await plugin.makeCurrencyTools()
132+
}
133+
})
134+
119135
it('Valid private key', async function () {
136+
const keys = await tools.createPrivateKey(WALLET_TYPE)
120137
await tools
121138
.derivePublicKey({
122139
type: WALLET_TYPE,
@@ -127,7 +144,8 @@ describe('currencyPlugins.spec', () => {
127144
id: '!'
128145
})
129146
.then(keys => {
130-
assert.deepEqual(keys.publicKeys[WALLET_FORMAT], fixture.xpub)
147+
const publicKey = keys.publicKeys[WALLET_FORMAT]
148+
assert.deepEqual(publicKey, fixture.xpub)
131149
})
132150
})
133151

@@ -145,6 +163,12 @@ describe('currencyPlugins.spec', () => {
145163
})
146164

147165
describe(`parseUri for Wallet type ${WALLET_TYPE}`, function () {
166+
before('Plugin', async function () {
167+
if (tools == null) {
168+
tools = await plugin.makeCurrencyTools()
169+
}
170+
})
171+
148172
Object.entries(fixture.parseUri).forEach(([test, [input, output]]) => {
149173
if (output != null) {
150174
it(test, async function () {
@@ -160,6 +184,12 @@ describe('currencyPlugins.spec', () => {
160184
})
161185

162186
describe(`encodeUri for Wallet type ${WALLET_TYPE}`, function () {
187+
before('Plugin', async function () {
188+
if (tools == null) {
189+
tools = await plugin.makeCurrencyTools()
190+
}
191+
})
192+
163193
Object.entries(fixture.encodeUri).forEach(([test, [input, output]]) => {
164194
if (output != null) {
165195
it(test, async function () {
@@ -179,6 +209,12 @@ describe('currencyPlugins.spec', () => {
179209

180210
if (getSplittableTypes == null) return
181211

212+
before('Plugin', async function () {
213+
if (tools == null) {
214+
tools = await plugin.makeCurrencyTools()
215+
}
216+
})
217+
182218
Object.keys(getSplittableTypes).forEach(format => {
183219
it(`Test for the wallet type ${format}`, function () {
184220
if (tools.getSplittableTypes == null) {

0 commit comments

Comments
 (0)