Skip to content

Commit d72be36

Browse files
committed
Adds a cosmos signer to the SDK
1 parent a212c3c commit d72be36

13 files changed

Lines changed: 2387 additions & 8 deletions

File tree

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/hex"
6+
"fmt"
7+
"os"
8+
9+
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
10+
basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1"
11+
cosmosSecp "cosmossdk.io/api/cosmos/crypto/secp256k1"
12+
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
13+
txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
14+
"github.com/cosmos/cosmos-proto/anyutil"
15+
"github.com/davecgh/go-spew/spew"
16+
tendermintClient "github.com/tendermint/tendermint/rpc/client/http"
17+
"github.com/tkhq/go-sdk"
18+
"github.com/tkhq/go-sdk/pkg/api/client"
19+
"github.com/tkhq/go-sdk/pkg/api/client/private_keys"
20+
"github.com/tkhq/go-sdk/pkg/api/models"
21+
"github.com/tkhq/go-sdk/pkg/apikey"
22+
"github.com/tkhq/go-sdk/pkg/signer/cosmos"
23+
"google.golang.org/protobuf/proto"
24+
"google.golang.org/protobuf/types/known/anypb"
25+
)
26+
27+
func getPublicKey(turnkeyClient *client.TurnkeyPublicAPI, orgID string, privateKeyID string, apiKey *apikey.Key) ([]byte, error) {
28+
getSenderPrivateKeyRequest := private_keys.NewPublicAPIServiceGetPrivateKeyParams().WithBody(&models.V1GetPrivateKeyRequest{
29+
OrganizationID: &orgID,
30+
PrivateKeyID: &privateKeyID,
31+
})
32+
33+
getSenderPrivateKeyResponse, err := turnkeyClient.PrivateKeys.PublicAPIServiceGetPrivateKey(getSenderPrivateKeyRequest, &sdk.Authenticator{Key: apiKey})
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
publicKeyBytes, err := hex.DecodeString(*getSenderPrivateKeyResponse.Payload.PrivateKey.PublicKey)
39+
if err != nil {
40+
return nil, err
41+
}
42+
43+
return cosmos.CompressPublicKey(publicKeyBytes), nil
44+
}
45+
46+
func main() {
47+
receiverPrivateKeyID := os.Getenv("RECEIVER_PRIVATE_KEY_ID")
48+
senderPrivateKeyID := os.Getenv("SENDER_PRIVATE_KEY_ID")
49+
apiPrivateKey := os.Getenv("API_PRIVATE_KEY")
50+
apiHost := os.Getenv("TURNKEY_BASE_URL")
51+
orgID := os.Getenv("ORGANIZATION_ID")
52+
53+
ctx := context.Background()
54+
55+
apiKey, err := apikey.FromTurnkeyPrivateKey(apiPrivateKey)
56+
if err != nil {
57+
panic(err)
58+
}
59+
60+
publicApiClient := client.NewHTTPClientWithConfig(nil, &client.TransportConfig{
61+
Host: apiHost,
62+
})
63+
64+
signer := cosmos.NewSigner(cosmos.SignerParams{
65+
TurnkeyClient: *publicApiClient,
66+
OrganizationID: orgID,
67+
ApiHost: apiHost,
68+
ApiKey: apiKey,
69+
})
70+
71+
fromPublicKey, err := getPublicKey(publicApiClient, orgID, senderPrivateKeyID, apiKey)
72+
if err != nil {
73+
panic(err)
74+
}
75+
76+
toPublicKey, err := getPublicKey(publicApiClient, orgID, receiverPrivateKeyID, apiKey)
77+
if err != nil {
78+
panic(err)
79+
}
80+
81+
toAddress := cosmos.CosmosAddressFromPublicKey(toPublicKey)
82+
fromAddress := cosmos.CosmosAddressFromPublicKey(fromPublicKey)
83+
84+
fmt.Println("Sending from: ")
85+
fmt.Println(fromAddress)
86+
fmt.Println("Sending to: ")
87+
fmt.Println(toAddress)
88+
89+
pk, err := anyutil.New(&cosmosSecp.PubKey{Key: fromPublicKey})
90+
if err != nil {
91+
panic(err)
92+
}
93+
94+
signerInfo := []*txv1beta1.SignerInfo{
95+
{
96+
PublicKey: pk,
97+
ModeInfo: &txv1beta1.ModeInfo{
98+
Sum: &txv1beta1.ModeInfo_Single_{
99+
Single: &txv1beta1.ModeInfo_Single{
100+
Mode: signingv1beta1.SignMode_SIGN_MODE_DIRECT,
101+
},
102+
},
103+
},
104+
Sequence: 2,
105+
},
106+
}
107+
108+
fee := &txv1beta1.Fee{
109+
Amount: []*basev1beta1.Coin{
110+
{
111+
Denom: "uatom",
112+
Amount: "1000",
113+
},
114+
},
115+
GasLimit: 200000,
116+
}
117+
118+
msg, err := anyutil.New(&bankv1beta1.MsgSend{
119+
FromAddress: fromAddress,
120+
ToAddress: toAddress,
121+
Amount: []*basev1beta1.Coin{
122+
{
123+
Denom: "uatom",
124+
Amount: "1",
125+
},
126+
},
127+
})
128+
if err != nil {
129+
panic(err)
130+
}
131+
132+
txBody := &txv1beta1.TxBody{
133+
Messages: []*anypb.Any{msg},
134+
Memo: "Turnkey demo",
135+
}
136+
137+
authInfo := &txv1beta1.AuthInfo{
138+
Fee: fee,
139+
SignerInfos: signerInfo,
140+
}
141+
142+
bodyBz, err := proto.Marshal(txBody)
143+
if err != nil {
144+
panic(err)
145+
}
146+
147+
authInfoBz, err := proto.Marshal(authInfo)
148+
if err != nil {
149+
panic(err)
150+
}
151+
152+
signBytes, err := proto.Marshal(&txv1beta1.SignDoc{
153+
BodyBytes: bodyBz,
154+
AuthInfoBytes: authInfoBz,
155+
ChainId: "cosmoshub-4",
156+
AccountNumber: 1878048,
157+
})
158+
if err != nil {
159+
panic(err)
160+
}
161+
162+
c, err := tendermintClient.New("https://cosmos-rpc.publicnode.com:443")
163+
if err != nil {
164+
panic(err)
165+
}
166+
167+
signature, err := signer.Sign(senderPrivateKeyID, signBytes)
168+
if err != nil {
169+
panic(err)
170+
}
171+
172+
tx := txv1beta1.Tx{
173+
Body: txBody,
174+
AuthInfo: authInfo,
175+
Signatures: [][]byte{
176+
signature,
177+
},
178+
}
179+
180+
txBytes, err := proto.Marshal(&tx)
181+
if err != nil {
182+
panic(err)
183+
}
184+
185+
result, err := c.BroadcastTxSync(ctx, txBytes)
186+
if err != nil {
187+
panic(err)
188+
}
189+
190+
spew.Dump(result)
191+
}

go.mod

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
module github.com/tkhq/go-sdk
22

3-
go 1.20
3+
go 1.21
44

55
require (
6+
cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273
7+
cosmossdk.io/x/tx v0.10.0
8+
github.com/cosmos/btcutil v1.0.5
9+
github.com/cosmos/cosmos-proto v1.0.0-beta.3
10+
github.com/cosmos/cosmos-sdk v0.47.5
11+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
612
github.com/go-openapi/errors v0.20.4
713
github.com/go-openapi/runtime v0.26.0
814
github.com/go-openapi/strfmt v0.21.7
@@ -11,29 +17,56 @@ require (
1117
github.com/google/uuid v1.3.1
1218
github.com/pkg/errors v0.9.1
1319
github.com/stretchr/testify v1.8.4
20+
github.com/tendermint/tendermint v0.35.9
21+
golang.org/x/crypto v0.14.0
22+
google.golang.org/protobuf v1.31.0
1423
)
1524

1625
require (
26+
cosmossdk.io/core v0.12.0 // indirect
1727
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
18-
github.com/davecgh/go-spew v1.1.1 // indirect
28+
github.com/btcsuite/btcd v0.22.1 // indirect
29+
github.com/cometbft/cometbft v0.38.0 // indirect
30+
github.com/cosmos/gogoproto v1.4.11 // indirect
31+
github.com/ethereum/go-ethereum v1.13.2 // indirect
1932
github.com/go-logr/logr v1.2.4 // indirect
2033
github.com/go-logr/stdr v1.2.2 // indirect
2134
github.com/go-openapi/analysis v0.21.4 // indirect
2235
github.com/go-openapi/jsonpointer v0.20.0 // indirect
2336
github.com/go-openapi/jsonreference v0.20.2 // indirect
2437
github.com/go-openapi/loads v0.21.2 // indirect
2538
github.com/go-openapi/spec v0.20.9 // indirect
39+
github.com/gogo/protobuf v1.3.2 // indirect
40+
github.com/golang/protobuf v1.5.3 // indirect
41+
github.com/google/go-cmp v0.6.0 // indirect
42+
github.com/gorilla/websocket v1.5.0 // indirect
2643
github.com/josharian/intern v1.0.0 // indirect
44+
github.com/klauspost/compress v1.17.0 // indirect
2745
github.com/mailru/easyjson v0.7.7 // indirect
46+
github.com/mattn/go-colorable v0.1.13 // indirect
47+
github.com/mattn/go-isatty v0.0.19 // indirect
2848
github.com/mitchellh/mapstructure v1.5.0 // indirect
49+
github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce // indirect
2950
github.com/oklog/ulid v1.3.1 // indirect
3051
github.com/opentracing/opentracing-go v1.2.0 // indirect
31-
github.com/pmezard/go-difflib v1.0.0 // indirect
32-
github.com/rogpeppe/go-internal v1.11.0 // indirect
52+
github.com/petermattis/goid v0.0.0-20230808133559-b036b712a89b // indirect
53+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
54+
github.com/prometheus/client_golang v1.17.0 // indirect
55+
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
56+
github.com/rs/zerolog v1.31.0 // indirect
57+
github.com/sasha-s/go-deadlock v0.3.1 // indirect
3358
go.mongodb.org/mongo-driver v1.12.1 // indirect
3459
go.opentelemetry.io/otel v1.17.0 // indirect
3560
go.opentelemetry.io/otel/metric v1.17.0 // indirect
3661
go.opentelemetry.io/otel/trace v1.17.0 // indirect
62+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
63+
golang.org/x/net v0.15.0 // indirect
64+
golang.org/x/sys v0.13.0 // indirect
65+
golang.org/x/text v0.13.0 // indirect
66+
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
67+
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
68+
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
69+
google.golang.org/grpc v1.58.2 // indirect
3770
gopkg.in/yaml.v2 v2.4.0 // indirect
3871
gopkg.in/yaml.v3 v3.0.1 // indirect
3972
)

0 commit comments

Comments
 (0)