Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

start use tonconnect logic from tongo #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ response:
See the [frontend SDK](https://github.com/ton-connect/sdk/tree/main/packages/sdk) for more details.

3. User approves connection and client receives signed payload with additional prefixes.
4. Client sends signed result to the backend. Backend checks correctnes of the all prefixes and signature correctness and returns auth token:
4. Client sends signed result to the backend. Backend checks correctness of the all prefixes and signature correctness and returns auth token:
```
<host>/ton-proof/checkProof
{
"address": "0:f63660ff947e5fe6ed4a8f729f1b24ef859497d0483aaa9d9ae48414297c4e1b", // user's address
"network": "-239", // "-239" for mainnet and "-1" for testnet
"network": "-239", // "-239" for mainnet and "-3" for testnet
"proof": {
"timestamp": 1668094767, // unix epoch seconds
"timestamp": 1668094767, // unix epoch seconds
"domain": {
"lengthBytes": 21,
"value": "ton-connect.github.io"
"value": "ton-connect.github.io"
},
"signature": "28tWSg8RDB3P/iIYupySINq1o3F5xLodndzNFHOtdi16Z+MuII8LAPnHLT3E6WTB27//qY4psU5Rf5/aJaIIAA==",
"payload": "E5B4ARS6CdOI2b5e1jz0jnS-x-a3DgfNXprrg_3pec0=" // payload from the step 1.
Expand Down
17 changes: 6 additions & 11 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,16 @@ import (
)

var Config = struct {
Port int `env:"PORT" envDefault:"8081"`
}{}

var Proof = struct {
PayloadSignatureKey string `env:"TONPROOF_PAYLOAD_SIGNATURE_KEY"`
PayloadLifeTimeSec int64 `env:"TONPROOF_PAYLOAD_LIFETIME_SEC" envDefault:"300"`
ProofLifeTimeSec int64 `env:"TONPROOF_PROOF_LIFETIME_SEC" envDefault:"300"`
ExampleDomain string `env:"TONPROOF_EXAMPLE_DOMAIN" envDefault:"ton-connect.github.io"`
Port int `env:"PORT" envDefault:"8081"`
Proof struct {
PayloadSignatureKey string `env:"TONPROOF_PAYLOAD_SIGNATURE_KEY,required"`
PayloadLifeTimeSec int64 `env:"TONPROOF_PAYLOAD_LIFETIME_SEC" envDefault:"300"`
ProofLifeTimeSec int64 `env:"TONPROOF_PROOF_LIFETIME_SEC" envDefault:"300"`
}
}{}

func LoadConfig() {
if err := env.Parse(&Config); err != nil {
log.Fatalf("config parsing failed: %v\n", err)
}
if err := env.Parse(&Proof); err != nil {
log.Panicf("[‼️ Config parsing failed] %+v\n", err)
}
}
42 changes: 11 additions & 31 deletions datatype/datatype.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,17 @@
package datatype

type Domain struct {
LengthBytes uint32 `json:"lengthBytes"`
Value string `json:"value"`
}

type MessageInfo struct {
Timestamp int64 `json:"timestamp"`
Domain Domain `json:"domain"`
Signature string `json:"signature"`
Payload string `json:"payload"`
StateInit string `json:"state_init"`
}

type TonProof struct {
Address string `json:"address"`
Network string `json:"network"`
Proof MessageInfo `json:"proof"`
}

type ParsedMessage struct {
Workchain int32
Address []byte
Timstamp int64
Domain Domain
Signature []byte
Payload string
StateInit string
}

type Payload struct {
ExpirtionTime int64
Signature string
Address string `json:"address"`
Network string `json:"network"`
Proof struct {
Timestamp int64 `json:"timestamp"`
Domain struct {
Value string `json:"value"`
} `json:"domain"`
Signature string `json:"signature"`
Payload string `json:"payload"`
StateInit string `json:"state_init"`
} `json:"proof"`
}

type AccountInfo struct {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/labstack/echo/v4 v4.9.1
github.com/sirupsen/logrus v1.9.0
github.com/tonkeeper/tongo v1.0.3
github.com/tonkeeper/tongo v1.0.16-0.20230523142154-0e273aa6fa60
)

require (
Expand All @@ -19,7 +19,7 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/exp v0.0.0-20230116083435-1de6713980de // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/net v0.0.0-20220728030405-41545e8bf201 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/text v0.3.7 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ github.com/snksoft/crc v1.1.0/go.mod h1:5/gUOsgAm7OmIhb6WJzw7w5g2zfJi4FrHYgGPdsh
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tonkeeper/tongo v1.0.3 h1:8NqSb5nUPh2Prp8UDXH5BQk035y6vxR46PE0aZAcsCs=
github.com/tonkeeper/tongo v1.0.3/go.mod h1:Nn/5t5MGQHBUuEm56O135FIYwk9WpPgDITjWPk+fPGc=
github.com/tonkeeper/tongo v1.0.16-0.20230523142154-0e273aa6fa60 h1:8TaiUBvX4NqvngDwobqC+N0I3p/vXtlK2sPEEVAGzCo=
github.com/tonkeeper/tongo v1.0.16-0.20230523142154-0e273aa6fa60/go.mod h1:LdOBjpUz6vLp1EdX3E0XLNks9YI5XMSqaQahfOMrBEY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20230116083435-1de6713980de h1:DBWn//IJw30uYCgERoxCg84hWtA97F4wMiKOIh00Uf0=
golang.org/x/exp v0.0.0-20230116083435-1de6713980de/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/net v0.0.0-20220728030405-41545e8bf201 h1:bvOltf3SADAfG05iRml8lAB3qjoEX5RCyN4K6G5v3N0=
golang.org/x/net v0.0.0-20220728030405-41545e8bf201/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
66 changes: 32 additions & 34 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package main
import (
"encoding/json"
"fmt"
"github.com/tonkeeper/tongo"
"io"
"net/http"
"time"

"github.com/tonkeeper/tongo"
"github.com/tonkeeper/tongo/tonconnect"

"github.com/golang-jwt/jwt"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
Expand All @@ -20,21 +22,21 @@ type jwtCustomClaims struct {
}

type handler struct {
sharedSecret string
payloadTtl time.Duration
tonConnectMainNet *tonconnect.Server
tonConnectTestNet *tonconnect.Server
}

func newHandler(sharedSecret string, payloadTtl time.Duration) *handler {
func newHandler(tonConnectMainNet, tonConnectTestNet *tonconnect.Server) *handler {
h := handler{
sharedSecret: sharedSecret,
payloadTtl: payloadTtl,
tonConnectMainNet: tonConnectMainNet,
tonConnectTestNet: tonConnectTestNet,
}
return &h
}

func (h *handler) ProofHandler(c echo.Context) error {
ctx := c.Request().Context()
log := log.WithContext(ctx).WithField("prefix", "ProofHandler")
log := log.WithContext(c.Request().Context()).WithField("prefix", "ProofHandler")

b, err := io.ReadAll(c.Request().Body)
if err != nil {
return c.JSON(HttpResErrorWithLog(err.Error(), http.StatusBadRequest, log))
Expand All @@ -45,30 +47,27 @@ func (h *handler) ProofHandler(c echo.Context) error {
return c.JSON(HttpResErrorWithLog(err.Error(), http.StatusBadRequest, log))
}

// check payload
err = checkPayload(tp.Proof.Payload, h.sharedSecret)
if err != nil {
return c.JSON(HttpResErrorWithLog("payload verification failed: "+err.Error(), http.StatusBadRequest, log))
}

parsed, err := ConvertTonProofMessage(ctx, &tp)
if err != nil {
return c.JSON(HttpResErrorWithLog(err.Error(), http.StatusBadRequest, log))
}

net := networks[tp.Network]
if net == nil {
var tonConnect *tonconnect.Server
switch tp.Network {
case "-239":
tonConnect = h.tonConnectMainNet
case "-3":
tonConnect = h.tonConnectTestNet
default:
return c.JSON(HttpResErrorWithLog(fmt.Sprintf("undefined network: %v", tp.Network), http.StatusBadRequest, log))
}
addr, err := tongo.ParseAccountID(tp.Address)
if net == nil {
return c.JSON(HttpResErrorWithLog(fmt.Sprintf("invalid account: %v", tp.Address), http.StatusBadRequest, log))
}
check, err := CheckProof(ctx, addr, net, parsed)
if err != nil {
return c.JSON(HttpResErrorWithLog("proof checking error: "+err.Error(), http.StatusBadRequest, log))
proof := tonconnect.Proof{
Address: tp.Address,
Proof: tonconnect.ProofData{
Timestamp: tp.Proof.Timestamp,
Domain: tp.Proof.Domain.Value,
Signature: tp.Proof.Signature,
Payload: tp.Proof.Payload,
StateInit: tp.Proof.StateInit,
},
}
if !check {
verified, _, err := tonConnect.CheckProof(&proof)
if err != nil || !verified {
return c.JSON(HttpResErrorWithLog("proof verification failed", http.StatusBadRequest, log))
}

Expand All @@ -80,23 +79,22 @@ func (h *handler) ProofHandler(c echo.Context) error {
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

t, err := token.SignedString([]byte(h.sharedSecret))
signedToken, err := token.SignedString([]byte(h.tonConnectMainNet.GetSecret()))
if err != nil {
return err
}

return c.JSON(http.StatusOK, echo.Map{
"token": t,
"token": signedToken,
})
}

func (h *handler) PayloadHandler(c echo.Context) error {
log := log.WithContext(c.Request().Context()).WithField("prefix", "PayloadHandler")

payload, err := generatePayload(h.sharedSecret, h.payloadTtl)
payload, err := h.tonConnectMainNet.GeneratePayload()
if err != nil {
c.JSON(HttpResErrorWithLog(err.Error(), http.StatusBadRequest, log))
return c.JSON(HttpResErrorWithLog(err.Error(), http.StatusBadRequest, log))
}

return c.JSON(http.StatusOK, echo.Map{
Expand Down
2 changes: 1 addition & 1 deletion http.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func registerHandlers(e *echo.Echo, h *handler) {
AllowMethods: []string{echo.GET},
}), middleware.JWTWithConfig(middleware.JWTConfig{
Claims: &jwtCustomClaims{},
SigningKey: []byte(config.Proof.PayloadSignatureKey),
SigningKey: []byte(config.Config.Proof.PayloadSignatureKey),
}))

}
28 changes: 19 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package main

import (
"fmt"
_ "net/http/pprof"

"github.com/tonkeeper/tongo/liteapi"
"time"
"github.com/tonkeeper/tongo/tonconnect"

"github.com/tonkeeper/tonproof/config"

_ "net/http/pprof"

"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
log "github.com/sirupsen/logrus"
Expand All @@ -25,17 +25,27 @@ func main() {
DisablePrintStack: false,
}))
e.Use(middleware.Logger())
var err error
networks["-239"], err = liteapi.NewClientWithDefaultMainnet()

mainNetClient, err := liteapi.NewClientWithDefaultMainnet()
if err != nil {
log.Fatal(err)
log.Fatalf("failed init mainnet liteapi client")
}
networks["-3"], err = liteapi.NewClientWithDefaultTestnet()
networks["-239"] = mainNetClient

testNetClient, err := liteapi.NewClientWithDefaultTestnet()
if err != nil {
log.Fatal(err)
log.Fatalf("failed init testnet liteapi client")
}
networks["-3"] = testNetClient

payloadLifeTime := config.Config.Proof.PayloadLifeTimeSec
proofLifeTime := config.Config.Proof.ProofLifeTimeSec
tonConnectMainNet, err := tonconnect.NewTonConnect(mainNetClient, config.Config.Proof.PayloadSignatureKey,
tonconnect.WithLifeTimePayload(payloadLifeTime), tonconnect.WithLifeTimeProof(proofLifeTime))
tonConnectTestNet, err := tonconnect.NewTonConnect(testNetClient, config.Config.Proof.PayloadSignatureKey,
tonconnect.WithLifeTimePayload(payloadLifeTime), tonconnect.WithLifeTimeProof(proofLifeTime))

h := newHandler(config.Proof.PayloadSignatureKey, time.Duration(config.Proof.ProofLifeTimeSec)*time.Second)
h := newHandler(tonConnectMainNet, tonConnectTestNet)

registerHandlers(e, h)

Expand Down
45 changes: 0 additions & 45 deletions nonce.go

This file was deleted.

Loading