Skip to content

Commit fd9da15

Browse files
Merge pull request #185 from JordiParraCrespo/authorize-channel
AuthorizeChannel
2 parents bf31eb6 + e9e4acb commit fd9da15

File tree

3 files changed

+182
-0
lines changed

3 files changed

+182
-0
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
#### xrpl
13+
14+
- `AuthorizeChannel` to authorize a payment channel.
15+
1016
### Refactored
1117

18+
#### xrpl
19+
1220
- `TxResponse` `Meta` field type changed to `TxMetadataBuilder`, enabling custom parsing for specific transactions metadata such as `Payment`, `NFTokenMint`, etc.
1321

1422
## [v0.1.13]

xrpl/wallet/authorize_channel.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package wallet
2+
3+
import (
4+
"encoding/hex"
5+
6+
binarycodec "github.com/Peersyst/xrpl-go/binary-codec"
7+
"github.com/Peersyst/xrpl-go/keypairs"
8+
)
9+
10+
// AuthorizeChannel returns a signature authorizing the redemption of a specific
11+
// amount of XRP from a payment channel.
12+
//
13+
// channelID identifies the payment channel.
14+
// amount is the amount to redeem, expressed in drops.
15+
//
16+
// Returns the signature or an error if the signature cannot be created.
17+
func AuthorizeChannel(channelID, amount string, wallet Wallet) (string, error) {
18+
encodedData, err := binarycodec.EncodeForSigningClaim(map[string]any{
19+
"Channel": channelID,
20+
"Amount": amount,
21+
})
22+
if err != nil {
23+
return "", err
24+
}
25+
hexData, err := hex.DecodeString(encodedData)
26+
if err != nil {
27+
return "", err
28+
}
29+
signedData, err := keypairs.Sign(string(hexData), wallet.PrivateKey)
30+
if err != nil {
31+
return "", err
32+
}
33+
return signedData, nil
34+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package wallet
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestAuthorizeChannel(t *testing.T) {
10+
// SECP256K1
11+
secpWallet, err := FromSeed("snGHNrPbHrdUcszeuDEigMdC1Lyyd", "")
12+
require.NoError(t, err)
13+
14+
// ED25519
15+
edWallet, err := FromSeed("sEdSuqBPSQaood2DmNYVkwWTn1oQTj2", "")
16+
require.NoError(t, err)
17+
18+
validChannelID := "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3"
19+
validAmount := "1000000"
20+
21+
tc := []struct {
22+
name string
23+
wallet Wallet
24+
channelID string
25+
amount string
26+
expectedSig string
27+
expectError bool
28+
}{
29+
{
30+
name: "pass - succeeds with secp256k1 seed",
31+
wallet: secpWallet,
32+
channelID: validChannelID,
33+
amount: validAmount,
34+
expectedSig: "304402204E7052F33DDAFAAA55C9F5B132A5E50EE95B2CF68C0902F61DFE77299BC893740220353640B951DCD24371C16868B3F91B78D38B6F3FD1E826413CDF891FA8250AAC",
35+
expectError: false,
36+
},
37+
{
38+
name: "pass - succeeds with ed25519 seed",
39+
wallet: edWallet,
40+
channelID: validChannelID,
41+
amount: validAmount,
42+
expectedSig: "7E1C217A3E4B3C107B7A356E665088B4FBA6464C48C58267BEF64975E3375EA338AE22E6714E3F5E734AE33E6B97AAD59058E1E196C1F92346FC1498D0674404",
43+
expectError: false,
44+
},
45+
{
46+
name: "pass - different amounts with secp256k1",
47+
wallet: secpWallet,
48+
channelID: validChannelID,
49+
amount: "5000000",
50+
expectedSig: "304402202DF006FDE665C8A15628991A946629DDD08F7677E75C54619A96E9872BCC615F02206689262B5F102992346E5D84CA4EC73E947906073E4B2873DCDBEE54AFE948C3",
51+
expectError: false,
52+
},
53+
{
54+
name: "pass - different amounts with ed25519",
55+
wallet: edWallet,
56+
channelID: validChannelID,
57+
amount: "5000000",
58+
expectedSig: "AEEFCF001061F4E0368805B8A56D116EA8B9E4879A69C5B56A5B7E0F6ABD63E63341D56247192104012BC6AAEA71B1C97E466F47DA0736EFAD462481B165FB0E",
59+
expectError: false,
60+
},
61+
{
62+
name: "pass - zero amount",
63+
wallet: secpWallet,
64+
channelID: validChannelID,
65+
amount: "0",
66+
expectedSig: "3044022069888D92E1F4104FAD7BA66D8DA69278E579FE6EDAF32E87ACF481A6383C4AEB02204E0286429FF9842724627A08EAFD1A8356A6B36994DA6F386D2363C5D3AAFE7C",
67+
expectError: false,
68+
},
69+
{
70+
name: "fail - fails with invalid channel ID format",
71+
wallet: secpWallet,
72+
channelID: "invalid-id",
73+
amount: validAmount,
74+
expectedSig: "",
75+
expectError: true,
76+
},
77+
{
78+
name: "fail - fails with invalid amount format",
79+
wallet: secpWallet,
80+
channelID: validChannelID,
81+
amount: "invalid-amount",
82+
expectedSig: "",
83+
expectError: true,
84+
},
85+
{
86+
name: "fail - empty channel ID",
87+
wallet: secpWallet,
88+
channelID: "",
89+
amount: validAmount,
90+
expectedSig: "",
91+
expectError: true,
92+
},
93+
{
94+
name: "fail - empty amount",
95+
wallet: secpWallet,
96+
channelID: validChannelID,
97+
amount: "",
98+
expectedSig: "",
99+
expectError: true,
100+
},
101+
{
102+
name: "fail - channel ID too short",
103+
wallet: secpWallet,
104+
channelID: "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB",
105+
amount: validAmount,
106+
expectedSig: "",
107+
expectError: true,
108+
},
109+
{
110+
name: "fail - channel ID too long",
111+
wallet: secpWallet,
112+
channelID: "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3A",
113+
amount: validAmount,
114+
expectedSig: "",
115+
expectError: true,
116+
},
117+
{
118+
name: "fail - channel ID with invalid hex characters",
119+
wallet: secpWallet,
120+
channelID: "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDBG",
121+
amount: validAmount,
122+
expectedSig: "",
123+
expectError: true,
124+
},
125+
}
126+
127+
for _, tt := range tc {
128+
t.Run(tt.name, func(t *testing.T) {
129+
signature, err := AuthorizeChannel(tt.channelID, tt.amount, tt.wallet)
130+
if tt.expectError {
131+
require.Error(t, err)
132+
require.Empty(t, signature)
133+
} else {
134+
require.NoError(t, err)
135+
require.NotEmpty(t, signature)
136+
require.Equal(t, tt.expectedSig, signature)
137+
}
138+
})
139+
}
140+
}

0 commit comments

Comments
 (0)