From fdbe4e64355cf02c9607bb42b2dd260081848911 Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:37:14 +0800 Subject: [PATCH 01/17] Create README.md --- go/README.md | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 go/README.md diff --git a/go/README.md b/go/README.md new file mode 100644 index 0000000..e4321cc --- /dev/null +++ b/go/README.md @@ -0,0 +1,167 @@ +# BNB Chain Telegram Token Faucet Demo + +## Introduction + +This project is a hands-on, full-stack demonstration of how users can **deploy their own BEP20 tokens**, interact with them via a **Telegram bot**, and access basic token utilities like **faucets** and **balance checks**. Built using **Golang** and deployed on **BNB Chain Testnet**, this example bridges smart contracts, blockchain interaction, and Telegram bot integration. + +Whether you're a developer exploring smart contract automation, a builder prototyping token tools, or just curious about how to hook blockchain into a Telegram experience — this project is for you. + +--- + +## What You Will Be Building + +By the end of this project, you'll have: + +- A **Solidity factory contract** deployed on BNB Chain testnet. +- A **Telegram bot** written in Go that can: + - Deploy a custom BEP20 token for each user + - Provide a **faucet** for the user’s own token + - Allow balance queries for any wallet address +- A running backend that uses `go-ethereum` to interact with smart contracts in real-time. + +--- + +## Key Learning Points + +- How to create and interact with a **factory smart contract** for BEP20 token deployment +- How to use **Golang** to: + - Send transactions + - Call contract methods + - Parse event logs +- How to integrate a **Telegram bot** for blockchain interaction +- How to manage user token data and provide tailored faucet services + +--- + +## Getting Started + +### Prerequisites + +Make sure you have the following installed: + +- Go 1.20+ +- Git +- Telegram account (to create and use the bot) +- BNB Chain testnet wallet (with test BNB) + +--- + +### 1. Clone the Repository + +```bash +git clone https://github.com/bnb-chain/example-hub.git +cd example-hub/go/bnb-faucet-demo +``` + +--- + +### 2. Create a `.env` File + +Create a `.env` file in the root of `bnb-faucet-demo`: + +```env +PRIVATE_KEY=your_faucet_wallet_private_key_without_0x +RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545/ +CHAIN_ID=97 +TOKEN_FACTORY_ADDRESS=0xYourDeployedFactoryContract +TG_BOT_TOKEN=your_telegram_bot_api_token +PORT=8080 +``` + +> Make sure your wallet has testnet BNB and the factory contract is deployed to the testnet. + +--- + +### 3. Install Dependencies + +```bash +go mod tidy +``` + +--- + +### 4. Run the Project + +```bash +go run main.go +``` + +This will start the Telegram bot and the backend faucet logic. + +--- + +## How to Use the Telegram Bot + +After running the project, talk to your Telegram bot (the one associated with `TG_BOT_TOKEN`) and use these commands: + +### `/deploy ` + +Example: +```bash +/deploy MemeToken MEME +``` + +- Deploys a new BEP20 token for **you** via the factory contract +- The bot will mint the tokens to the faucet wallet + +--- + +### `/faucet
` + +Example: +```bash +/faucet 0xAbC123...456 +``` + +- Sends 10 tokens of **your token** to the given address + +--- + +### `/balance
` + +Example: +```bash +/balance 0xAbC123...456 +``` + +- Checks the BEP20 balance of the given address **for your token** + +--- + +## Example Flow + +1. User sends `/deploy TestCoin TST` +2. Bot responds with deployed token address +3. User sends `/faucet 0x123...abc` +4. Bot sends 10 TST to that address +5. User sends `/balance 0x123...abc` +6. Bot responds with the token balance for that wallet + +--- + +## Project Structure + +``` +go/bnb-faucet-demo/ +├── main.go # Entry point +├── bot.go # Telegram bot logic +├── faucet.go # Token sending logic +├── balance.go # Balance query logic +├── utils/ +│ └── env.go # Loads environment variables +├── .env # Your config (not committed) +├── go.mod +└── README.md +``` + +--- + +## License + +MIT License + +--- + +## Contributions + +Pull requests, ideas, and issues are welcome! This is a learning-focused example — feel free to extend it or build your own launchpad product from it. From 2b2169d8b5088fe29ba3fa8c45797dd3d5299bc2 Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:38:54 +0800 Subject: [PATCH 02/17] Create env.go --- go/utils/env.go | 1 + 1 file changed, 1 insertion(+) create mode 100644 go/utils/env.go diff --git a/go/utils/env.go b/go/utils/env.go new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/go/utils/env.go @@ -0,0 +1 @@ + From 58ebaa54290db154a73c4baac5e1bbd2e7ab013a Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:39:39 +0800 Subject: [PATCH 03/17] Update env.go --- go/utils/env.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/go/utils/env.go b/go/utils/env.go index 8b13789..089ea68 100644 --- a/go/utils/env.go +++ b/go/utils/env.go @@ -1 +1,26 @@ +package utils + +import ( + "log" + "os" + + "github.com/joho/godotenv" +) + +// LoadEnv loads environment variables from a .env file if present +func LoadEnv() { + err := godotenv.Load() + if err != nil { + log.Println("⚠️ No .env file found. Using system environment variables.") + } +} + +// MustGetEnv returns the value of the environment variable or panics if not set +func MustGetEnv(key string) string { + value := os.Getenv(key) + if value == "" { + log.Fatalf("❌ Required environment variable %s not set", key) + } + return value +} From 98fe2f5cf2c52f246eb7e80b741023c4a0b5218d Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:40:04 +0800 Subject: [PATCH 04/17] Delete go/utils directory --- go/utils/env.go | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 go/utils/env.go diff --git a/go/utils/env.go b/go/utils/env.go deleted file mode 100644 index 089ea68..0000000 --- a/go/utils/env.go +++ /dev/null @@ -1,26 +0,0 @@ -package utils - -import ( - "log" - "os" - - "github.com/joho/godotenv" -) - -// LoadEnv loads environment variables from a .env file if present -func LoadEnv() { - err := godotenv.Load() - if err != nil { - log.Println("⚠️ No .env file found. Using system environment variables.") - } -} - -// MustGetEnv returns the value of the environment variable or panics if not set -func MustGetEnv(key string) string { - value := os.Getenv(key) - if value == "" { - log.Fatalf("❌ Required environment variable %s not set", key) - } - return value -} - From abcc278009b1ab0d735d84cef38f7daa55c07f5a Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:40:52 +0800 Subject: [PATCH 05/17] Create tg-token-launch-example --- go/tg-token-launch-example | 1 + 1 file changed, 1 insertion(+) create mode 100644 go/tg-token-launch-example diff --git a/go/tg-token-launch-example b/go/tg-token-launch-example new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/go/tg-token-launch-example @@ -0,0 +1 @@ + From 312f551ee19c5b3fdfdf910ab8339d3cadc818d1 Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:41:10 +0800 Subject: [PATCH 06/17] Delete go/ --- go/tg-token-launch-example | 1 - 1 file changed, 1 deletion(-) delete mode 100644 go/tg-token-launch-example diff --git a/go/tg-token-launch-example b/go/tg-token-launch-example deleted file mode 100644 index 8b13789..0000000 --- a/go/tg-token-launch-example +++ /dev/null @@ -1 +0,0 @@ - From cfff3d2ff4dfeb32f964e965c550d9ed74c3768b Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:41:43 +0800 Subject: [PATCH 07/17] Delete go/README.md --- go/README.md | 167 --------------------------------------------------- 1 file changed, 167 deletions(-) delete mode 100644 go/README.md diff --git a/go/README.md b/go/README.md deleted file mode 100644 index e4321cc..0000000 --- a/go/README.md +++ /dev/null @@ -1,167 +0,0 @@ -# BNB Chain Telegram Token Faucet Demo - -## Introduction - -This project is a hands-on, full-stack demonstration of how users can **deploy their own BEP20 tokens**, interact with them via a **Telegram bot**, and access basic token utilities like **faucets** and **balance checks**. Built using **Golang** and deployed on **BNB Chain Testnet**, this example bridges smart contracts, blockchain interaction, and Telegram bot integration. - -Whether you're a developer exploring smart contract automation, a builder prototyping token tools, or just curious about how to hook blockchain into a Telegram experience — this project is for you. - ---- - -## What You Will Be Building - -By the end of this project, you'll have: - -- A **Solidity factory contract** deployed on BNB Chain testnet. -- A **Telegram bot** written in Go that can: - - Deploy a custom BEP20 token for each user - - Provide a **faucet** for the user’s own token - - Allow balance queries for any wallet address -- A running backend that uses `go-ethereum` to interact with smart contracts in real-time. - ---- - -## Key Learning Points - -- How to create and interact with a **factory smart contract** for BEP20 token deployment -- How to use **Golang** to: - - Send transactions - - Call contract methods - - Parse event logs -- How to integrate a **Telegram bot** for blockchain interaction -- How to manage user token data and provide tailored faucet services - ---- - -## Getting Started - -### Prerequisites - -Make sure you have the following installed: - -- Go 1.20+ -- Git -- Telegram account (to create and use the bot) -- BNB Chain testnet wallet (with test BNB) - ---- - -### 1. Clone the Repository - -```bash -git clone https://github.com/bnb-chain/example-hub.git -cd example-hub/go/bnb-faucet-demo -``` - ---- - -### 2. Create a `.env` File - -Create a `.env` file in the root of `bnb-faucet-demo`: - -```env -PRIVATE_KEY=your_faucet_wallet_private_key_without_0x -RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545/ -CHAIN_ID=97 -TOKEN_FACTORY_ADDRESS=0xYourDeployedFactoryContract -TG_BOT_TOKEN=your_telegram_bot_api_token -PORT=8080 -``` - -> Make sure your wallet has testnet BNB and the factory contract is deployed to the testnet. - ---- - -### 3. Install Dependencies - -```bash -go mod tidy -``` - ---- - -### 4. Run the Project - -```bash -go run main.go -``` - -This will start the Telegram bot and the backend faucet logic. - ---- - -## How to Use the Telegram Bot - -After running the project, talk to your Telegram bot (the one associated with `TG_BOT_TOKEN`) and use these commands: - -### `/deploy ` - -Example: -```bash -/deploy MemeToken MEME -``` - -- Deploys a new BEP20 token for **you** via the factory contract -- The bot will mint the tokens to the faucet wallet - ---- - -### `/faucet
` - -Example: -```bash -/faucet 0xAbC123...456 -``` - -- Sends 10 tokens of **your token** to the given address - ---- - -### `/balance
` - -Example: -```bash -/balance 0xAbC123...456 -``` - -- Checks the BEP20 balance of the given address **for your token** - ---- - -## Example Flow - -1. User sends `/deploy TestCoin TST` -2. Bot responds with deployed token address -3. User sends `/faucet 0x123...abc` -4. Bot sends 10 TST to that address -5. User sends `/balance 0x123...abc` -6. Bot responds with the token balance for that wallet - ---- - -## Project Structure - -``` -go/bnb-faucet-demo/ -├── main.go # Entry point -├── bot.go # Telegram bot logic -├── faucet.go # Token sending logic -├── balance.go # Balance query logic -├── utils/ -│ └── env.go # Loads environment variables -├── .env # Your config (not committed) -├── go.mod -└── README.md -``` - ---- - -## License - -MIT License - ---- - -## Contributions - -Pull requests, ideas, and issues are welcome! This is a learning-focused example — feel free to extend it or build your own launchpad product from it. From 3b00042812e5f9468a244e0792076eac3dcfdfdd Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:42:08 +0800 Subject: [PATCH 08/17] Create README.md --- go/tg-token-launch-example/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 go/tg-token-launch-example/README.md diff --git a/go/tg-token-launch-example/README.md b/go/tg-token-launch-example/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/go/tg-token-launch-example/README.md @@ -0,0 +1 @@ + From 076468f66a9452c9938909683d5089ae77905a6f Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sat, 5 Apr 2025 17:42:41 +0800 Subject: [PATCH 09/17] Update README.md --- go/tg-token-launch-example/README.md | 167 +++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/go/tg-token-launch-example/README.md b/go/tg-token-launch-example/README.md index 8b13789..b79c794 100644 --- a/go/tg-token-launch-example/README.md +++ b/go/tg-token-launch-example/README.md @@ -1 +1,168 @@ +# BNB Chain Telegram Token Faucet Demo + +## Introduction + +This project is a hands-on, full-stack demonstration of how users can **deploy their own BEP20 tokens**, interact with them via a **Telegram bot**, and access basic token utilities like **faucets** and **balance checks**. Built using **Golang** and deployed on **BNB Chain Testnet**, this example bridges smart contracts, blockchain interaction, and Telegram bot integration. + +Whether you're a developer exploring smart contract automation, a builder prototyping token tools, or just curious about how to hook blockchain into a Telegram experience — this project is for you. + +--- + +## What You Will Be Building + +By the end of this project, you'll have: + +- A **Solidity factory contract** deployed on BNB Chain testnet. +- A **Telegram bot** written in Go that can: + - Deploy a custom BEP20 token for each user + - Provide a **faucet** for the user’s own token + - Allow balance queries for any wallet address +- A running backend that uses `go-ethereum` to interact with smart contracts in real-time. + +--- + +## Key Learning Points + +- How to create and interact with a **factory smart contract** for BEP20 token deployment +- How to use **Golang** to: + - Send transactions + - Call contract methods + - Parse event logs +- How to integrate a **Telegram bot** for blockchain interaction +- How to manage user token data and provide tailored faucet services + +--- + +## Getting Started + +### Prerequisites + +Make sure you have the following installed: + +- Go 1.20+ +- Git +- Telegram account (to create and use the bot) +- BNB Chain testnet wallet (with test BNB) + +--- + +### 1. Clone the Repository + +```bash +git clone https://github.com/bnb-chain/example-hub.git +cd example-hub/go/bnb-faucet-demo +``` + +--- + +### 2. Create a `.env` File + +Create a `.env` file in the root of `bnb-faucet-demo`: + +```env +PRIVATE_KEY=your_faucet_wallet_private_key_without_0x +RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545/ +CHAIN_ID=97 +TOKEN_FACTORY_ADDRESS=0xYourDeployedFactoryContract +TG_BOT_TOKEN=your_telegram_bot_api_token +PORT=8080 +``` + +> Make sure your wallet has testnet BNB and the factory contract is deployed to the testnet. + +--- + +### 3. Install Dependencies + +```bash +go mod tidy +``` + +--- + +### 4. Run the Project + +```bash +go run main.go +``` + +This will start the Telegram bot and the backend faucet logic. + +--- + +## How to Use the Telegram Bot + +After running the project, talk to your Telegram bot (the one associated with `TG_BOT_TOKEN`) and use these commands: + +### `/deploy ` + +Example: +```bash +/deploy MemeToken MEME +``` + +- Deploys a new BEP20 token for **you** via the factory contract +- The bot will mint the tokens to the faucet wallet + +--- + +### `/faucet
` + +Example: +```bash +/faucet 0xAbC123...456 +``` + +- Sends 10 tokens of **your token** to the given address + +--- + +### `/balance
` + +Example: +```bash +/balance 0xAbC123...456 +``` + +- Checks the BEP20 balance of the given address **for your token** + +--- + +## Example Flow + +1. User sends `/deploy TestCoin TST` +2. Bot responds with deployed token address +3. User sends `/faucet 0x123...abc` +4. Bot sends 10 TST to that address +5. User sends `/balance 0x123...abc` +6. Bot responds with the token balance for that wallet + +--- + +## Project Structure + +``` +go/bnb-faucet-demo/ +├── main.go # Entry point +├── bot.go # Telegram bot logic +├── faucet.go # Token sending logic +├── balance.go # Balance query logic +├── utils/ +│ └── env.go # Loads environment variables +├── .env # Your config (not committed) +├── go.mod +└── README.md +``` + +--- + +## License + +MIT License + +--- + +## Contributions + +Pull requests, ideas, and issues are welcome! This is a learning-focused example — feel free to extend it or build your own launchpad product from it. From f1b55bc09a4940d8f3b7a8de3c08b7784b994093 Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sun, 6 Apr 2025 17:39:56 +0800 Subject: [PATCH 10/17] Create balance.go --- go/tg-token-launch-example/balance.go | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 go/tg-token-launch-example/balance.go diff --git a/go/tg-token-launch-example/balance.go b/go/tg-token-launch-example/balance.go new file mode 100644 index 0000000..a32edc3 --- /dev/null +++ b/go/tg-token-launch-example/balance.go @@ -0,0 +1,52 @@ +package main + +import ( + "context" + "fmt" + "math/big" + "os" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +// GetTokenBalance returns the BEP20 token balance of a given address +func GetTokenBalance(tokenAddress string, walletAddress string) (string, error) { + client, err := ethclient.Dial(os.Getenv("RPC_URL")) + if err != nil { + return "", err + } + defer client.Close() + + contract := common.HexToAddress(tokenAddress) + account := common.HexToAddress(walletAddress) + + tokenABI := `[{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"}]` + parsedABI, err := abi.JSON(strings.NewReader(tokenABI)) + if err != nil { + return "", err + } + + data, err := parsedABI.Pack("balanceOf", account) + if err != nil { + return "", err + } + + callMsg := ethereum.CallMsg{To: &contract, Data: data} + output, err := client.CallContract(context.Background(), callMsg, nil) + if err != nil { + return "", err + } + + var balance *big.Int + err = parsedABI.UnpackIntoInterface(&balance, "balanceOf", output) + if err != nil { + return "", err + } + + // Return in human-readable format (e.g. 1.23 tokens) + human := new(big.Float).Quo(new(big.Float).SetInt(balance), big.NewFloat(1e18)) + return fmt.Sprintf("%s tokens", human.Text('f', 6)), nil +} From 222f05780763282009a8c4d896e169fd2b25277f Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sun, 6 Apr 2025 17:40:11 +0800 Subject: [PATCH 11/17] Create faucet.go --- go/tg-token-launch-example/faucet.go | 85 ++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 go/tg-token-launch-example/faucet.go diff --git a/go/tg-token-launch-example/faucet.go b/go/tg-token-launch-example/faucet.go new file mode 100644 index 0000000..c386395 --- /dev/null +++ b/go/tg-token-launch-example/faucet.go @@ -0,0 +1,85 @@ +package main + +import ( + "context" + "crypto/ecdsa" + "encoding/hex" + "fmt" + "log" + "math/big" + "os" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +// SendToken transfers tokens from the faucet to a user address +func SendToken(tokenAddress string, to string) (string, error) { + client, err := ethclient.Dial(os.Getenv("RPC_URL")) + if err != nil { + return "", err + } + defer client.Close() + + privateKeyBytes, err := hex.DecodeString(strings.TrimPrefix(os.Getenv("PRIVATE_KEY"), "0x")) + if err != nil { + return "", fmt.Errorf("invalid private key: %v", err) + } + privateKey, err := crypto.ToECDSA(privateKeyBytes) + if err != nil { + return "", err + } + + fromAddress := crypto.PubkeyToAddress(privateKey.Public().(*ecdsa.PublicKey)) + nonce, err := client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + return "", err + } + + gasPrice, err := client.SuggestGasPrice(context.Background()) + if err != nil { + return "", err + } + + toAddress := common.HexToAddress(to) + contractAddress := common.HexToAddress(tokenAddress) + + tokenABI := `[{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"type":"function"}]` + parsedABI, err := abi.JSON(strings.NewReader(tokenABI)) + if err != nil { + return "", err + } + + // Send 10 tokens + amount := new(big.Int).Mul(big.NewInt(10), big.NewInt(1e18)) + data, err := parsedABI.Pack("transfer", toAddress, amount) + if err != nil { + return "", err + } + + msg := ethereum.CallMsg{To: &contractAddress, Data: data} + gasLimit, err := client.EstimateGas(context.Background(), msg) + if err != nil { + gasLimit = uint64(60000) // fallback + } + + tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data) + chainID := big.NewInt(97) // BNB Testnet + signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey) + if err != nil { + return "", err + } + + err = client.SendTransaction(context.Background(), signedTx) + if err != nil { + return "", err + } + + log.Printf("✅ Sent tokens to %s, tx: %s", to, signedTx.Hash().Hex()) + return signedTx.Hash().Hex(), nil +} From 8e45493dc9d382887f177e2636b4d30084c5fddd Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sun, 6 Apr 2025 17:40:32 +0800 Subject: [PATCH 12/17] Create bot.go --- go/tg-token-launch-example/bot.go | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 go/tg-token-launch-example/bot.go diff --git a/go/tg-token-launch-example/bot.go b/go/tg-token-launch-example/bot.go new file mode 100644 index 0000000..d1585fa --- /dev/null +++ b/go/tg-token-launch-example/bot.go @@ -0,0 +1,87 @@ +package main + +import ( + "log" + "os" + "strings" + + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" +) + +var userTokens = make(map[int64]string) // telegram user ID -> token address + +func StartTelegramBot() { + bot, err := tgbotapi.NewBotAPI(os.Getenv("TG_BOT_TOKEN")) + if err != nil { + log.Panic(err) + } + bot.Debug = false + + u := tgbotapi.NewUpdate(0) + u.Timeout = 60 + updates, _ := bot.GetUpdatesChan(u) + + for update := range updates { + if update.Message == nil { + continue + } + + userID := update.Message.From.ID + args := strings.Split(update.Message.Text, " ") + + switch { + case strings.HasPrefix(update.Message.Text, "/deploy"): + if len(args) != 3 { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Usage: /deploy ")) + continue + } + name := args[1] + symbol := args[2] + + tokenAddress, err := DeployToken(name, symbol) + if err != nil { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Error deploying token: "+err.Error())) + } else { + userTokens[userID] = tokenAddress + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "✅ Token deployed: "+tokenAddress)) + } + + case strings.HasPrefix(update.Message.Text, "/faucet"): + if len(args) != 2 { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Usage: /faucet
")) + continue + } + tokenAddr := userTokens[userID] + if tokenAddr == "" { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "❌ You need to /deploy a token first")) + continue + } + txHash, err := SendToken(tokenAddr, args[1]) + if err != nil { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Error: "+err.Error())) + } else { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Sent! TX: "+txHash)) + } + + case strings.HasPrefix(update.Message.Text, "/balance"): + if len(args) != 2 { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Usage: /balance
")) + continue + } + tokenAddr := userTokens[userID] + if tokenAddr == "" { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "❌ You need to /deploy a token first")) + continue + } + balance, err := GetTokenBalance(tokenAddr, args[1]) + if err != nil { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Error: "+err.Error())) + } else { + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Balance: "+balance)) + } + + default: + bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Available commands:\n/deploy \n/faucet
\n/balance
")) + } + } +} From 45a4717692b5740b8abf4bb9b01b778237b3e357 Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sun, 6 Apr 2025 17:41:21 +0800 Subject: [PATCH 13/17] Create env.go --- go/tg-token-launch-example/utils/env.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 go/tg-token-launch-example/utils/env.go diff --git a/go/tg-token-launch-example/utils/env.go b/go/tg-token-launch-example/utils/env.go new file mode 100644 index 0000000..d3e9d6b --- /dev/null +++ b/go/tg-token-launch-example/utils/env.go @@ -0,0 +1,25 @@ +package utils + +import ( + "log" + "os" + + "github.com/joho/godotenv" +) + +// LoadEnv loads environment variables from a .env file if present +func LoadEnv() { + err := godotenv.Load() + if err != nil { + log.Println("⚠️ No .env file found. Using system environment variables.") + } +} + +// MustGetEnv returns the value of the environment variable or panics if not set +func MustGetEnv(key string) string { + value := os.Getenv(key) + if value == "" { + log.Fatalf("❌ Required environment variable %s not set", key) + } + return value +} From f2f17bf04a8c1c623987f0fca3b8071b45f62634 Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sun, 6 Apr 2025 17:42:10 +0800 Subject: [PATCH 14/17] Create main.go --- go/tg-token-launch-example/main.go | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 go/tg-token-launch-example/main.go diff --git a/go/tg-token-launch-example/main.go b/go/tg-token-launch-example/main.go new file mode 100644 index 0000000..b5b2834 --- /dev/null +++ b/go/tg-token-launch-example/main.go @@ -0,0 +1,10 @@ +package main + +import ( + "bnb-faucet-demo/utils" +) + +func main() { + utils.LoadEnv() + StartTelegramBot() +} From 4ea154fe2e04e04291b344ce29eeb4299c583a1c Mon Sep 17 00:00:00 2001 From: decentraliao Date: Sun, 6 Apr 2025 17:42:36 +0800 Subject: [PATCH 15/17] Create .env.example --- go/tg-token-launch-example/.env.example | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 go/tg-token-launch-example/.env.example diff --git a/go/tg-token-launch-example/.env.example b/go/tg-token-launch-example/.env.example new file mode 100644 index 0000000..20e92c0 --- /dev/null +++ b/go/tg-token-launch-example/.env.example @@ -0,0 +1,17 @@ +# Wallet private key (without 0x prefix) +PRIVATE_KEY=your_faucet_wallet_private_key + +# RPC endpoint for BNB Chain testnet +RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545/ + +# Telegram Bot Token from BotFather +TG_BOT_TOKEN=your_telegram_bot_token + +# Factory contract deployed to testnet +TOKEN_FACTORY_ADDRESS=0xYourFactoryContractAddress + +# Chain ID for BNB Testnet +CHAIN_ID=97 + +# HTTP port for internal APIs (if any) +PORT=8080 From 5fe6b4f182120fc69d4882459425e244c8d0f2ca Mon Sep 17 00:00:00 2001 From: lucasodra Date: Mon, 7 Apr 2025 04:04:58 +0800 Subject: [PATCH 16/17] Completed example --- go/tg-token-launch-example/.env.example | 4 +- go/tg-token-launch-example/Factory.sol | 20 +++ go/tg-token-launch-example/README.md | 165 +++++++++-------- go/tg-token-launch-example/balance.go | 1 + go/tg-token-launch-example/bot.go | 6 +- go/tg-token-launch-example/factory.go | 119 +++++++++++++ go/tg-token-launch-example/faucet.go | 34 +++- go/tg-token-launch-example/go.mod | 42 +++++ go/tg-token-launch-example/go.sum | 226 ++++++++++++++++++++++++ go/tg-token-launch-example/main.go | 2 +- go/tg-token-launch-example/utils/env.go | 36 +++- 11 files changed, 566 insertions(+), 89 deletions(-) create mode 100644 go/tg-token-launch-example/Factory.sol create mode 100644 go/tg-token-launch-example/factory.go create mode 100644 go/tg-token-launch-example/go.mod create mode 100644 go/tg-token-launch-example/go.sum diff --git a/go/tg-token-launch-example/.env.example b/go/tg-token-launch-example/.env.example index 20e92c0..74ef730 100644 --- a/go/tg-token-launch-example/.env.example +++ b/go/tg-token-launch-example/.env.example @@ -1,5 +1,5 @@ -# Wallet private key (without 0x prefix) -PRIVATE_KEY=your_faucet_wallet_private_key +# Wallet private key using Mnemonic +MNEMONIC=your_faucet_wallet_private_key # RPC endpoint for BNB Chain testnet RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545/ diff --git a/go/tg-token-launch-example/Factory.sol b/go/tg-token-launch-example/Factory.sol new file mode 100644 index 0000000..3314c2e --- /dev/null +++ b/go/tg-token-launch-example/Factory.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract TokenFactory { + event TokenDeployed(address indexed owner, address indexed token, string name, string symbol); + + function deployToken(string memory name, string memory symbol, address initialRecipient) external returns (address) { + ERC20Token newToken = new ERC20Token(name, symbol, initialRecipient); + emit TokenDeployed(initialRecipient, address(newToken), name, symbol); + return address(newToken); + } +} + +contract ERC20Token is ERC20 { + constructor(string memory name, string memory symbol, address to) ERC20(name, symbol) { + _mint(to, 1_000_000 * 10 ** decimals()); + } +} diff --git a/go/tg-token-launch-example/README.md b/go/tg-token-launch-example/README.md index b79c794..332d38b 100644 --- a/go/tg-token-launch-example/README.md +++ b/go/tg-token-launch-example/README.md @@ -1,78 +1,82 @@ -# BNB Chain Telegram Token Faucet Demo +# 🧪 BNB Chain Telegram Token Launch & Faucet Demo ## Introduction -This project is a hands-on, full-stack demonstration of how users can **deploy their own BEP20 tokens**, interact with them via a **Telegram bot**, and access basic token utilities like **faucets** and **balance checks**. Built using **Golang** and deployed on **BNB Chain Testnet**, this example bridges smart contracts, blockchain interaction, and Telegram bot integration. +This project is a complete hands-on demo for creating and interacting with your own BEP20 token on **BNB Chain Testnet**, using a **Telegram bot interface** and a backend written in **Go**. -Whether you're a developer exploring smart contract automation, a builder prototyping token tools, or just curious about how to hook blockchain into a Telegram experience — this project is for you. +It showcases how to: +- Deploy BEP20 tokens via a **Solidity Factory contract** +- Interact with contracts using **Golang and go-ethereum** +- Let users manage tokens via a **Telegram Bot** --- -## What You Will Be Building +## 🔧 What You Will Be Building -By the end of this project, you'll have: +- A **Solidity factory contract** that deploys ERC20-compatible tokens +- A **Telegram bot** that lets each user: + - Deploy their own token + - Use a faucet to send that token + - Check token balances +- A **Golang backend** that listens to the Telegram bot and interacts with contracts in real time -- A **Solidity factory contract** deployed on BNB Chain testnet. -- A **Telegram bot** written in Go that can: - - Deploy a custom BEP20 token for each user - - Provide a **faucet** for the user’s own token - - Allow balance queries for any wallet address -- A running backend that uses `go-ethereum` to interact with smart contracts in real-time. +--- + +## 🚀 Getting Started + +### ✅ 1. Create Your Wallet (Trust Wallet or MetaMask) + +Create a new wallet and switch to **BNB Chain Testnet**. +Then grab some test BNB from the official [BNB Faucet](https://testnet.bnbchain.org/faucet-smart). --- -## Key Learning Points +### ✅ 2. Create a Telegram Bot + +Use [@BotFather](https://t.me/BotFather) to create a new Telegram bot. -- How to create and interact with a **factory smart contract** for BEP20 token deployment -- How to use **Golang** to: - - Send transactions - - Call contract methods - - Parse event logs -- How to integrate a **Telegram bot** for blockchain interaction -- How to manage user token data and provide tailored faucet services +- Run `/newbot` and follow the instructions +- Save the API token it gives you — you'll need it for `.env` --- -## Getting Started +### ✅ 3. Deploy the Factory Contract -### Prerequisites +You can: +- Use our deployed example on testnet: + `0xeCb781015873dc48a4c0BCdf3ba74dF9269061C3` -Make sure you have the following installed: +**OR** -- Go 1.20+ -- Git -- Telegram account (to create and use the bot) -- BNB Chain testnet wallet (with test BNB) +- Deploy `Factory.sol` using **Hardhat**, **Foundry**, or **Remix** --- -### 1. Clone the Repository +### ✅ 4. Clone the Repository ```bash -git clone https://github.com/bnb-chain/example-hub.git -cd example-hub/go/bnb-faucet-demo +git clone https://github.com/your-org/example-hub.git +cd example-hub/go/tg-token-launch-example ``` --- -### 2. Create a `.env` File +### ✅ 5. Configure Environment Variables -Create a `.env` file in the root of `bnb-faucet-demo`: +Create a `.env` file: ```env -PRIVATE_KEY=your_faucet_wallet_private_key_without_0x +MNEMONIC=your_mnemonic_phrase_without_quotes RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545/ -CHAIN_ID=97 -TOKEN_FACTORY_ADDRESS=0xYourDeployedFactoryContract +TOKEN_FACTORY_ADDRESS=0xeCb781015873dc48a4c0BCdf3ba74dF9269061C3 TG_BOT_TOKEN=your_telegram_bot_api_token -PORT=8080 ``` -> Make sure your wallet has testnet BNB and the factory contract is deployed to the testnet. - --- -### 3. Install Dependencies +### ✅ 6. Install Go Dependencies + +Make sure you're using **Go 1.20+**: ```bash go mod tidy @@ -80,89 +84,100 @@ go mod tidy --- -### 4. Run the Project +### ✅ 7. Run the Bot ```bash -go run main.go +go run . ``` -This will start the Telegram bot and the backend faucet logic. +If everything is set up, you'll see logs showing that the Telegram bot is running. --- -## How to Use the Telegram Bot +## 🤖 Telegram Bot Commands + +After starting your bot, go chat with it on Telegram. -After running the project, talk to your Telegram bot (the one associated with `TG_BOT_TOKEN`) and use these commands: +### `/deploy ` -### `/deploy ` +Deploys a new BEP20 token for your user. -Example: ```bash -/deploy MemeToken MEME +/deploy TestCoin TST ``` -- Deploys a new BEP20 token for **you** via the factory contract -- The bot will mint the tokens to the faucet wallet - --- ### `/faucet
` -Example: +Sends 10 tokens of the user’s token to the given wallet address. + ```bash -/faucet 0xAbC123...456 +/faucet 0xYourFriendWallet ``` -- Sends 10 tokens of **your token** to the given address - --- ### `/balance
` -Example: +Checks the token balance for the given wallet address. + ```bash -/balance 0xAbC123...456 +/balance 0xYourWallet ``` -- Checks the BEP20 balance of the given address **for your token** - --- -## Example Flow +## ✅ Example User Flow -1. User sends `/deploy TestCoin TST` -2. Bot responds with deployed token address -3. User sends `/faucet 0x123...abc` -4. Bot sends 10 TST to that address -5. User sends `/balance 0x123...abc` -6. Bot responds with the token balance for that wallet +1. User sends `/deploy Meme MEME` +2. Bot responds: `✅ Token deployed: 0x...` +3. User sends `/faucet 0xabc...` +4. Bot sends 10 MEME tokens +5. User sends `/balance 0xabc...` +6. Bot replies with token balance --- -## Project Structure +## 🗂 Project Structure ``` -go/bnb-faucet-demo/ +tg-token-launch-example/ +├── Factory.sol # Solidity factory contract ├── main.go # Entry point ├── bot.go # Telegram bot logic -├── faucet.go # Token sending logic -├── balance.go # Balance query logic +├── faucet.go # Send tokens +├── balance.go # Check balances +├── factory.go # Deploy tokens via contract ├── utils/ -│ └── env.go # Loads environment variables -├── .env # Your config (not committed) -├── go.mod +│ └── env.go # Loads .env + key derivation +├── go.mod / go.sum # Go module dependencies +├── .env # Your local config (not committed) └── README.md ``` --- -## License +## 🧠 Learning Points -MIT License +- Deriving Ethereum wallets from mnemonic phrases (BIP-44) +- Sending transactions and reading logs using go-ethereum +- Interacting with deployed smart contracts +- Parsing custom events in Go +- Building bots with Telegram Bot API --- -## Contributions +## 🪪 License -Pull requests, ideas, and issues are welcome! This is a learning-focused example — feel free to extend it or build your own launchpad product from it. +MIT — use this as a base to build your own launchpad, faucet, or dev tool. + +--- + +## 🙌 Contributing + +PRs and ideas are welcome! This is built for developers looking to quickly bootstrap real-world BNBChain projects. + +--- +### 🌐 Built with 💛 by the BNB Chain Dev Community diff --git a/go/tg-token-launch-example/balance.go b/go/tg-token-launch-example/balance.go index a32edc3..f8d1424 100644 --- a/go/tg-token-launch-example/balance.go +++ b/go/tg-token-launch-example/balance.go @@ -7,6 +7,7 @@ import ( "os" "strings" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" diff --git a/go/tg-token-launch-example/bot.go b/go/tg-token-launch-example/bot.go index d1585fa..0d3ddf7 100644 --- a/go/tg-token-launch-example/bot.go +++ b/go/tg-token-launch-example/bot.go @@ -42,7 +42,7 @@ func StartTelegramBot() { if err != nil { bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Error deploying token: "+err.Error())) } else { - userTokens[userID] = tokenAddress + userTokens[int64(userID)] = tokenAddress bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "✅ Token deployed: "+tokenAddress)) } @@ -51,7 +51,7 @@ func StartTelegramBot() { bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Usage: /faucet
")) continue } - tokenAddr := userTokens[userID] + tokenAddr := userTokens[int64(userID)] if tokenAddr == "" { bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "❌ You need to /deploy a token first")) continue @@ -68,7 +68,7 @@ func StartTelegramBot() { bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "Usage: /balance
")) continue } - tokenAddr := userTokens[userID] + tokenAddr := userTokens[int64(userID)] if tokenAddr == "" { bot.Send(tgbotapi.NewMessage(update.Message.Chat.ID, "❌ You need to /deploy a token first")) continue diff --git a/go/tg-token-launch-example/factory.go b/go/tg-token-launch-example/factory.go new file mode 100644 index 0000000..c2c804a --- /dev/null +++ b/go/tg-token-launch-example/factory.go @@ -0,0 +1,119 @@ +package main + +import ( + "context" + "crypto/ecdsa" + "fmt" + "log" + "math/big" + "os" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +// DeployToken calls the factory contract and deploys a new token +func DeployToken(name, symbol string) (string, error) { + client, err := ethclient.Dial(os.Getenv("RPC_URL")) + if err != nil { + return "", err + } + defer client.Close() + + privateKey, err := getPrivateKey() + if err != nil { + return "", err + } + + fromAddress := crypto.PubkeyToAddress(*privateKey.Public().(*ecdsa.PublicKey)) + nonce, err := client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + return "", err + } + + gasPrice, err := client.SuggestGasPrice(context.Background()) + if err != nil { + return "", err + } + + // TokenFactory ABI + const factoryABI = `[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"initialRecipient","type":"address"}],"name":"deployToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"}]` + parsedABI, err := abi.JSON(strings.NewReader(factoryABI)) + if err != nil { + return "", err + } + + // Pack deployToken call + data, err := parsedABI.Pack("deployToken", name, symbol, fromAddress) + if err != nil { + return "", err + } + + // Set contract address (TokenFactory) + contractAddress := common.HexToAddress(os.Getenv("TOKEN_FACTORY_ADDRESS")) + + msg := ethereum.CallMsg{ + From: fromAddress, + To: &contractAddress, + Data: data, + } + gasLimit, err := client.EstimateGas(context.Background(), msg) + if err != nil { + gasLimit = uint64(300_000) // fallback + } + + // Create and sign transaction + tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data) + chainID := big.NewInt(97) // BNB Testnet + signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey) + if err != nil { + return "", err + } + + err = client.SendTransaction(context.Background(), signedTx) + if err != nil { + return "", err + } + + log.Println("⛓ Sent deployToken transaction:", signedTx.Hash().Hex()) + + // OPTIONAL: Wait for receipt and get deployed address from logs + receipt, err := waitForReceipt(client, signedTx.Hash()) + if err != nil { + return "", err + } + + // Parse event log to get deployed token address + factoryAddr := common.HexToAddress(os.Getenv("TOKEN_FACTORY_ADDRESS")) + + for _, vLog := range receipt.Logs { + if vLog.Address == factoryAddr && len(vLog.Topics) >= 3 { + // Debug print to confirm + log.Println("Log from factory:") + log.Println(" Topic[1] (token):", vLog.Topics[1].Hex()) + log.Println(" Topic[2] (owner):", vLog.Topics[2].Hex()) + + tokenAddress := common.HexToAddress(vLog.Topics[2].Hex()) + log.Println("🎉 Token deployed to:", tokenAddress.Hex()) + return tokenAddress.Hex(), nil + } + } + + return "", fmt.Errorf("could not find deployed token address in logs") +} + +// Waits for transaction receipt +func waitForReceipt(client *ethclient.Client, txHash common.Hash) (*types.Receipt, error) { + ctx := context.Background() + for { + receipt, err := client.TransactionReceipt(ctx, txHash) + if err == nil { + return receipt, nil + } + } +} diff --git a/go/tg-token-launch-example/faucet.go b/go/tg-token-launch-example/faucet.go index c386395..f50a199 100644 --- a/go/tg-token-launch-example/faucet.go +++ b/go/tg-token-launch-example/faucet.go @@ -10,6 +10,8 @@ import ( "os" "strings" + "tg-token-launch-example/utils" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -26,16 +28,12 @@ func SendToken(tokenAddress string, to string) (string, error) { } defer client.Close() - privateKeyBytes, err := hex.DecodeString(strings.TrimPrefix(os.Getenv("PRIVATE_KEY"), "0x")) - if err != nil { - return "", fmt.Errorf("invalid private key: %v", err) - } - privateKey, err := crypto.ToECDSA(privateKeyBytes) + privateKey, err := getPrivateKey() if err != nil { return "", err } - fromAddress := crypto.PubkeyToAddress(privateKey.Public().(*ecdsa.PublicKey)) + fromAddress := crypto.PubkeyToAddress(*privateKey.Public().(*ecdsa.PublicKey)) nonce, err := client.PendingNonceAt(context.Background(), fromAddress) if err != nil { return "", err @@ -83,3 +81,27 @@ func SendToken(tokenAddress string, to string) (string, error) { log.Printf("✅ Sent tokens to %s, tx: %s", to, signedTx.Hash().Hex()) return signedTx.Hash().Hex(), nil } + +// getPrivateKey retrieves the private key from mnemonic or env +func getPrivateKey() (*ecdsa.PrivateKey, error) { + mnemonic := os.Getenv("MNEMONIC") + if mnemonic != "" { + privateKey, err := utils.DerivePrivateKeyFromMnemonic(mnemonic) + if err != nil { + return nil, fmt.Errorf("failed to derive private key from mnemonic: %v", err) + } + return privateKey, nil + } + + rawKey := os.Getenv("PRIVATE_KEY") + if rawKey == "" { + return nil, fmt.Errorf("neither MNEMONIC nor PRIVATE_KEY is set") + } + + privateKeyBytes, err := hex.DecodeString(strings.TrimPrefix(rawKey, "0x")) + if err != nil { + return nil, fmt.Errorf("invalid PRIVATE_KEY: %v", err) + } + + return crypto.ToECDSA(privateKeyBytes) +} diff --git a/go/tg-token-launch-example/go.mod b/go/tg-token-launch-example/go.mod new file mode 100644 index 0000000..a28d776 --- /dev/null +++ b/go/tg-token-launch-example/go.mod @@ -0,0 +1,42 @@ +module tg-token-launch-example + +go 1.24.2 + +require ( + github.com/ethereum/go-ethereum v1.15.7 + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible + github.com/joho/godotenv v1.5.1 +) + +require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/bits-and-blooms/bitset v1.17.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/consensys/bavard v0.1.22 // indirect + github.com/consensys/gnark-crypto v0.14.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/supranational/blst v0.3.14 // indirect + github.com/technoweenie/multipartstreamer v1.0.1 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + golang.org/x/crypto v0.35.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/go/tg-token-launch-example/go.sum b/go/tg-token-launch-example/go.sum new file mode 100644 index 0000000..ebecc6b --- /dev/null +++ b/go/tg-token-launch-example/go.sum @@ -0,0 +1,226 @@ +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.17.0 h1:1X2TS7aHz1ELcC0yU1y2stUs/0ig5oMU6STFZGrhvHI= +github.com/bits-and-blooms/bitset v1.17.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= +github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.22 h1:Uw2CGvbXSZWhqK59X0VG/zOjpTFuOMcPLStrp1ihI0A= +github.com/consensys/bavard v0.1.22/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= +github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= +github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= +github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= +github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.11 h1:b51Dsm+rEg7anFRUMGB8hODXHvNfcRKzz9vcj8wSdUs= +github.com/ethereum/go-ethereum v1.13.11/go.mod h1:gFtlVORuUcT+UUIcJ/veCNjkuOSujCi338uSHJrYAew= +github.com/ethereum/go-ethereum v1.15.7 h1:vm1XXruZVnqtODBgqFaTclzP0xAvCvQIDKyFNUA1JpY= +github.com/ethereum/go-ethereum v1.15.7/go.mod h1:+S9k+jFzlyVTNcYGvqFhzN/SFhI6vA+aOY4T5tLSPL0= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= +github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= +github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= +github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/go/tg-token-launch-example/main.go b/go/tg-token-launch-example/main.go index b5b2834..4260454 100644 --- a/go/tg-token-launch-example/main.go +++ b/go/tg-token-launch-example/main.go @@ -1,7 +1,7 @@ package main import ( - "bnb-faucet-demo/utils" + "tg-token-launch-example/utils" ) func main() { diff --git a/go/tg-token-launch-example/utils/env.go b/go/tg-token-launch-example/utils/env.go index d3e9d6b..dc04b98 100644 --- a/go/tg-token-launch-example/utils/env.go +++ b/go/tg-token-launch-example/utils/env.go @@ -1,13 +1,18 @@ package utils import ( + "crypto/ecdsa" "log" "os" + "github.com/ethereum/go-ethereum/crypto" "github.com/joho/godotenv" + + bip39 "github.com/tyler-smith/go-bip39" + bip32 "github.com/tyler-smith/go-bip32" ) -// LoadEnv loads environment variables from a .env file if present +// LoadEnv loads .env file func LoadEnv() { err := godotenv.Load() if err != nil { @@ -15,7 +20,7 @@ func LoadEnv() { } } -// MustGetEnv returns the value of the environment variable or panics if not set +// MustGetEnv returns a required env variable func MustGetEnv(key string) string { value := os.Getenv(key) if value == "" { @@ -23,3 +28,30 @@ func MustGetEnv(key string) string { } return value } + +// DerivePrivateKeyFromMnemonic generates an Ethereum-compatible private key from a BIP39 mnemonic +func DerivePrivateKeyFromMnemonic(mnemonic string) (*ecdsa.PrivateKey, error) { + // Generate seed from mnemonic + seed := bip39.NewSeed(mnemonic, "") + + // Master key + masterKey, err := bip32.NewMasterKey(seed) + if err != nil { + return nil, err + } + + // Derive Ethereum path: m/44'/60'/0'/0/0 + purpose, _ := masterKey.NewChildKey(bip32.FirstHardenedChild + 44) + coinType, _ := purpose.NewChildKey(bip32.FirstHardenedChild + 60) + account, _ := coinType.NewChildKey(bip32.FirstHardenedChild + 0) + change, _ := account.NewChildKey(0) + addressIndex, _ := change.NewChildKey(0) + + // Convert to Ethereum ecdsa.PrivateKey + privateKey, err := crypto.ToECDSA(addressIndex.Key) + if err != nil { + return nil, err + } + + return privateKey, nil +} From dda67edf42478c680f18fa50ce0fba1c5dc322e0 Mon Sep 17 00:00:00 2001 From: lucasodra Date: Mon, 7 Apr 2025 04:09:40 +0800 Subject: [PATCH 17/17] Update list.json --- web/list.json | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/web/list.json b/web/list.json index e53c216..356ab96 100644 --- a/web/list.json +++ b/web/list.json @@ -63,5 +63,24 @@ "guide": "https://github.com/bnb-chain/example-hub/blob/main/python/pancake-swap-example/README.md", "otherLink": "", "imgUrl": "https://dex-bin.bnbstatic.com/static/dapp-uploads/O6j-gZp80QCa524NkHfpf" + }, + { + "caseTitle": "Telegram Token Launch & Faucet Demo (Go + BNB Testnet)", + "caseDesc": "A Go-powered backend with a Telegram bot that allows users to deploy their own BEP-20 tokens, send them via faucet, and check balances—all using a factory smart contract on the BNB Chain Testnet.", + "tags": [ + "BSC", + "BNB Chain", + "Telegram Bot", + "Web3", + "Golang", + "Smart Contracts", + "BEP-20" + ], + "github": "https://github.com/bnb-chain/example-hub/tree/main/go/tg-token-launch-example", + "replit": "", + "video": {}, + "guide": "https://github.com/bnb-chain/example-hub/blob/main/go/tg-token-launch-example/README.md", + "otherLink": "", + "imgUrl": "" } -] +] \ No newline at end of file