-
Notifications
You must be signed in to change notification settings - Fork 7
/
sign.go
123 lines (102 loc) · 2.67 KB
/
sign.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package tonconnect
import (
"context"
"fmt"
"strconv"
"golang.org/x/sync/errgroup"
)
type signDataRequest struct {
ID string `json:"id"`
Method string `json:"method"`
Params []SignData `json:"params"`
}
type SignData struct {
SchemaCRC uint32 `json:"schema_crc"`
Cell []byte `json:"cell"`
PublicKey string `json:"publicKey,omitempty"`
}
type signDataResponse struct {
ID string `json:"id"`
Result signDataResult `json:"result,omitempty"`
Error *struct {
Code uint64 `json:"code"`
Message string `json:"message"`
} `json:"error,omitempty"`
}
type signDataOpt = func(*SignData)
func (s *Session) SignData(ctx context.Context, data SignData, options ...bridgeMessageOption) (*signDataResult, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
g, ctx := errgroup.WithContext(ctx)
msgs := make(chan bridgeMessage)
id := s.LastRequestID + 1
g.Go(func() error {
req := signDataRequest{
ID: strconv.FormatUint(id, 10),
Method: "signData",
Params: []SignData{data},
}
err := s.sendMessage(ctx, req, "signData", options...)
if err == nil {
s.LastRequestID = id
}
return err
})
var res signDataResult
g.Go(func() error {
for {
select {
case <-ctx.Done():
return ctx.Err()
case msg := <-msgs:
msgID, err := msg.Message.ID.Int64()
if err == nil {
s.LastRequestID = uint64(msgID)
}
if int64(id) == msgID {
if msg.Message.Error != nil {
if msg.Message.Error.Message != "" {
return fmt.Errorf("tonconnect: %s", msg.Message.Error.Message)
}
switch msg.Message.Error.Code {
case 1:
return fmt.Errorf("tonconnect: bad request")
case 100:
return fmt.Errorf("tonconnect: unknown app")
case 300:
return fmt.Errorf("tonconnect: user declined the signature request")
case 400:
return fmt.Errorf("tonconnect: %q method is not supported", "signData")
default:
return fmt.Errorf("tonconnect: unknown data sign error")
}
}
cancel()
var ok bool
res, ok = msg.Message.Result.(signDataResult)
if !ok {
return fmt.Errorf("tonconnect: data sign result expected to be of type %q", "signDataResult")
}
return nil
}
}
}
})
g.Go(func() error {
return s.connectToBridge(ctx, s.BridgeURL, msgs)
})
err := g.Wait()
return &res, err
}
func NewSignDataRequest(schemaCRC uint32, cell []byte, options ...signDataOpt) (*SignData, error) {
data := &SignData{SchemaCRC: schemaCRC, Cell: cell}
for _, opt := range options {
opt(data)
}
return data, nil
}
func WithPublicKey(pubkey string) signDataOpt {
return func(data *SignData) {
data.PublicKey = pubkey
}
}