From c4cf047419a7c4baa937fb85b2db491cef2648da Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 10:01:39 +0530 Subject: [PATCH 01/11] Add script to generate LPS distribution JSON --- scripts/generate-lps-distribution-json.py | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 scripts/generate-lps-distribution-json.py diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py new file mode 100644 index 0000000..1bfe3fa --- /dev/null +++ b/scripts/generate-lps-distribution-json.py @@ -0,0 +1,83 @@ +import sys +import requests +import pandas as pd +import json +import re + +def get_excel_download_url(google_sheet_url): + """ + Convert a Google Sheets URL to its Excel export URL. + """ + match = re.search(r'/d/([a-zA-Z0-9-_]+)', google_sheet_url) + if not match: + raise ValueError('Invalid Google Sheets URL') + sheet_id = match.group(1) + # Export the first sheet as Excel + return f'https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=xlsx&id={sheet_id}' + + +def download_excel(url, output_path): + """ + Download the Excel file from the given URL. + """ + response = requests.get(url) + if response.status_code != 200: + raise Exception(f'Failed to download file: {response.status_code}') + with open(output_path, 'wb') as f: + f.write(response.content) + + +def convert_excel_to_json(excel_path, json_path): + """ + Read the Excel file, extract columns from the 'Genesis Allocation' sheet, and save as JSON. + """ + df = pd.read_excel(excel_path, sheet_name='Genesis Allocation') + # Ensure columns exist + required_columns = [ + 'Placeholder', + 'Laconic Address', + 'Total LPS Allocation', + 'Lock (months)', + 'Vest (months)' + ] + for col in required_columns: + if col not in df.columns: + raise Exception(f'Missing required column: {col}') + + result = {} + for _, row in df.iterrows(): + placeholder = str(row['Placeholder']) if not pd.isna(row['Placeholder']) else '' + laconic_address = str(row['Laconic Address']) if not pd.isna(row['Laconic Address']) else '' + # Use laconic_address as key if placeholder is missing or empty + key = placeholder if placeholder and placeholder.lower() != 'nan' else laconic_address + if not key or key.lower() == 'nan': + continue + entry = { + 'total_lps_allocation': row['Total LPS Allocation'] if not pd.isna(row['Total LPS Allocation']) else None, + 'lock_months': row['Lock (months)'] if not pd.isna(row['Lock (months)']) else None, + 'vest_months': row['Vest (months)'] if not pd.isna(row['Vest (months)']) else None, + 'laconic_address': row['Laconic Address'] if not pd.isna(row['Laconic Address']) else None + } + result[key] = entry + + with open(json_path, 'w') as f: + json.dump(result, f, indent=2) + + +def main(): + if len(sys.argv) != 2: + print('Usage: python download_and_convert_google_sheet.py ') + sys.exit(1) + google_sheet_url = sys.argv[1] + excel_url = get_excel_download_url(google_sheet_url) + excel_path = 'sheet.xlsx' + json_path = 'distribution.json' + print(f'Downloading Excel file from: {excel_url}') + download_excel(excel_url, excel_path) + print('Converting Excel to JSON...') + convert_excel_to_json(excel_path, json_path) + print(f'JSON saved to {json_path}') + + +if __name__ == '__main__': + main() -- 2.45.2 From bb112677a3011e2f7302ee9f0f5736506a939fd9 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 10:58:10 +0530 Subject: [PATCH 02/11] Add script to run generate distribution JSON script --- docs/run-first-validator.md | 9 ++++++++ scripts/generate-lps-distribution-json.py | 4 ---- scripts/generate-lps-lock.sh | 28 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 scripts/generate-lps-lock.sh diff --git a/docs/run-first-validator.md b/docs/run-first-validator.md index 8e212f5..46ff836 100644 --- a/docs/run-first-validator.md +++ b/docs/run-first-validator.md @@ -4,6 +4,7 @@ - [ansible](playbooks/README.md#ansible-installation) - [laconic-so](https://github.com/cerc-io/stack-orchestrator/?tab=readme-ov-file#install) +- Link to LPS distribution spreadsheet ## Export testnet state @@ -45,6 +46,14 @@ - Copy over the exported `testnet-state.json` file to target machine +- Generate LPS lockup distribution JSON file + + ``` + bash ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh "" + ``` + + - This will generate the `distribution.json` file at `~/cerc/laconicd-stack/distribution.json` + - Copy over the LPS lockup distribution `distribution.json` file to target machine - Set envs: diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py index 1bfe3fa..abdb82d 100644 --- a/scripts/generate-lps-distribution-json.py +++ b/scripts/generate-lps-distribution-json.py @@ -15,7 +15,6 @@ def get_excel_download_url(google_sheet_url): # Export the first sheet as Excel return f'https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=xlsx&id={sheet_id}' - def download_excel(url, output_path): """ Download the Excel file from the given URL. @@ -26,7 +25,6 @@ def download_excel(url, output_path): with open(output_path, 'wb') as f: f.write(response.content) - def convert_excel_to_json(excel_path, json_path): """ Read the Excel file, extract columns from the 'Genesis Allocation' sheet, and save as JSON. @@ -63,7 +61,6 @@ def convert_excel_to_json(excel_path, json_path): with open(json_path, 'w') as f: json.dump(result, f, indent=2) - def main(): if len(sys.argv) != 2: print('Usage: python download_and_convert_google_sheet.py ') @@ -78,6 +75,5 @@ def main(): convert_excel_to_json(excel_path, json_path) print(f'JSON saved to {json_path}') - if __name__ == '__main__': main() diff --git a/scripts/generate-lps-lock.sh b/scripts/generate-lps-lock.sh new file mode 100644 index 0000000..a634a9b --- /dev/null +++ b/scripts/generate-lps-lock.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +sheet_url="$1" +venv_dir="$PWD/venv-lps-lock" +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Create venv if it doesn't exist +if [ ! -d "$venv_dir" ]; then + python3 -m venv "$venv_dir" +fi + +# Activate venv and install dependencies +"$venv_dir/bin/pip" install --upgrade pip > /dev/null +"$venv_dir/bin/pip" install requests pandas openpyxl > /dev/null + +echo "Running LPS lock generation script..." +"$venv_dir/bin/python" "$script_dir/generate-lps-distribution-json.py" "$sheet_url" + +# Clean up venv +echo "Cleaning up..." +rm -rf "$venv_dir" -- 2.45.2 From 779af9b2e8e47eb5f95968210e080cf1278c4146 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 11:21:43 +0530 Subject: [PATCH 03/11] Update script to accept file path --- docs/run-first-validator.md | 4 ++-- scripts/generate-lps-distribution-json.py | 16 ++++++++++------ scripts/generate-lps-lock.sh | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/run-first-validator.md b/docs/run-first-validator.md index 46ff836..f362fb3 100644 --- a/docs/run-first-validator.md +++ b/docs/run-first-validator.md @@ -4,7 +4,7 @@ - [ansible](playbooks/README.md#ansible-installation) - [laconic-so](https://github.com/cerc-io/stack-orchestrator/?tab=readme-ov-file#install) -- Link to LPS distribution spreadsheet +- LPS distribution spreadsheet URL or excel file path ## Export testnet state @@ -49,7 +49,7 @@ - Generate LPS lockup distribution JSON file ``` - bash ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh "" + bash ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh "" ``` - This will generate the `distribution.json` file at `~/cerc/laconicd-stack/distribution.json` diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py index abdb82d..602f15a 100644 --- a/scripts/generate-lps-distribution-json.py +++ b/scripts/generate-lps-distribution-json.py @@ -63,14 +63,18 @@ def convert_excel_to_json(excel_path, json_path): def main(): if len(sys.argv) != 2: - print('Usage: python download_and_convert_google_sheet.py ') + print('Usage: python generate-lps-distribution-json.py ') sys.exit(1) - google_sheet_url = sys.argv[1] - excel_url = get_excel_download_url(google_sheet_url) - excel_path = 'sheet.xlsx' + input_arg = sys.argv[1] + if input_arg.startswith('https://'): + excel_url = get_excel_download_url(input_arg) + excel_path = 'sheet.xlsx' + print(f'Downloading Excel file from: {excel_url}') + download_excel(excel_url, excel_path) + else: + excel_path = input_arg + print(f'Using Excel file at path: {excel_path}') json_path = 'distribution.json' - print(f'Downloading Excel file from: {excel_url}') - download_excel(excel_url, excel_path) print('Converting Excel to JSON...') convert_excel_to_json(excel_path, json_path) print(f'JSON saved to {json_path}') diff --git a/scripts/generate-lps-lock.sh b/scripts/generate-lps-lock.sh index a634a9b..1cbf776 100644 --- a/scripts/generate-lps-lock.sh +++ b/scripts/generate-lps-lock.sh @@ -17,8 +17,8 @@ if [ ! -d "$venv_dir" ]; then fi # Activate venv and install dependencies -"$venv_dir/bin/pip" install --upgrade pip > /dev/null -"$venv_dir/bin/pip" install requests pandas openpyxl > /dev/null +"$venv_dir/bin/pip" install --upgrade pip +"$venv_dir/bin/pip" install requests pandas openpyxl echo "Running LPS lock generation script..." "$venv_dir/bin/python" "$script_dir/generate-lps-distribution-json.py" "$sheet_url" -- 2.45.2 From ec1e885799d30d386a0a7b19049acf042da7eac1 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 11:25:53 +0530 Subject: [PATCH 04/11] Make script executable --- docs/run-first-validator.md | 2 +- scripts/generate-lps-lock.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 scripts/generate-lps-lock.sh diff --git a/docs/run-first-validator.md b/docs/run-first-validator.md index f362fb3..65cba46 100644 --- a/docs/run-first-validator.md +++ b/docs/run-first-validator.md @@ -49,7 +49,7 @@ - Generate LPS lockup distribution JSON file ``` - bash ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh "" + ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh "" ``` - This will generate the `distribution.json` file at `~/cerc/laconicd-stack/distribution.json` diff --git a/scripts/generate-lps-lock.sh b/scripts/generate-lps-lock.sh old mode 100644 new mode 100755 -- 2.45.2 From 66e813580026f7f7e0fcf1cb9af0c2fc6935f0a1 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 11:52:10 +0530 Subject: [PATCH 05/11] Add comments in script --- scripts/generate-lps-distribution-json.py | 41 +++++++++++++-------- scripts/generate-lps-lock.sh | 43 ++++++++++++++++++++--- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py index 602f15a..792afeb 100644 --- a/scripts/generate-lps-distribution-json.py +++ b/scripts/generate-lps-distribution-json.py @@ -3,16 +3,18 @@ import requests import pandas as pd import json import re +import argparse def get_excel_download_url(google_sheet_url): """ Convert a Google Sheets URL to its Excel export URL. """ + # Extract the Sheet ID to construct the download URL match = re.search(r'/d/([a-zA-Z0-9-_]+)', google_sheet_url) if not match: raise ValueError('Invalid Google Sheets URL') sheet_id = match.group(1) - # Export the first sheet as Excel + # Export the entire spreadsheet as an Excel file (includes all sheets) return f'https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=xlsx&id={sheet_id}' def download_excel(url, output_path): @@ -25,11 +27,11 @@ def download_excel(url, output_path): with open(output_path, 'wb') as f: f.write(response.content) -def convert_excel_to_json(excel_path, json_path): +def convert_excel_to_json(excel_path, json_path, sheet_name): """ - Read the Excel file, extract columns from the 'Genesis Allocation' sheet, and save as JSON. + Read the Excel file, extract columns from the specified sheet, and save as JSON. """ - df = pd.read_excel(excel_path, sheet_name='Genesis Allocation') + df = pd.read_excel(excel_path, sheet_name=sheet_name) # Ensure columns exist required_columns = [ 'Placeholder', @@ -45,39 +47,48 @@ def convert_excel_to_json(excel_path, json_path): result = {} for _, row in df.iterrows(): placeholder = str(row['Placeholder']) if not pd.isna(row['Placeholder']) else '' + laconic_address = str(row['Laconic Address']) if not pd.isna(row['Laconic Address']) else '' + # Use laconic_address as key if placeholder is missing or empty key = placeholder if placeholder and placeholder.lower() != 'nan' else laconic_address + + # Skip the row if both 'Placeholder' and 'Laconic Address' are missing or invalid if not key or key.lower() == 'nan': continue + entry = { 'total_lps_allocation': row['Total LPS Allocation'] if not pd.isna(row['Total LPS Allocation']) else None, 'lock_months': row['Lock (months)'] if not pd.isna(row['Lock (months)']) else None, 'vest_months': row['Vest (months)'] if not pd.isna(row['Vest (months)']) else None, 'laconic_address': row['Laconic Address'] if not pd.isna(row['Laconic Address']) else None } + result[key] = entry with open(json_path, 'w') as f: json.dump(result, f, indent=2) def main(): - if len(sys.argv) != 2: - print('Usage: python generate-lps-distribution-json.py ') - sys.exit(1) - input_arg = sys.argv[1] - if input_arg.startswith('https://'): - excel_url = get_excel_download_url(input_arg) + parser = argparse.ArgumentParser(description='Generate LPS distribution JSON from Excel or Google Sheet') + parser.add_argument('--input', '-i', required=True, help='Input: Google Sheet URL or local Excel file path') + parser.add_argument('--output', '-o', default='distribution.json', help='Output JSON file path (default: distribution.json)') + parser.add_argument('--sheet', '-s', default='Genesis Allocation', help='Sheet name to read (default: Genesis Allocation)') + + args = parser.parse_args() + + if args.input.startswith('https://'): + excel_url = get_excel_download_url(args.input) excel_path = 'sheet.xlsx' print(f'Downloading Excel file from: {excel_url}') download_excel(excel_url, excel_path) else: - excel_path = input_arg + excel_path = args.input print(f'Using Excel file at path: {excel_path}') - json_path = 'distribution.json' - print('Converting Excel to JSON...') - convert_excel_to_json(excel_path, json_path) - print(f'JSON saved to {json_path}') + + print(f'Converting Excel to JSON (sheet: {args.sheet})...') + convert_excel_to_json(excel_path, args.output, args.sheet) + print(f'JSON saved to {args.output}') if __name__ == '__main__': main() diff --git a/scripts/generate-lps-lock.sh b/scripts/generate-lps-lock.sh index 1cbf776..72c6936 100755 --- a/scripts/generate-lps-lock.sh +++ b/scripts/generate-lps-lock.sh @@ -2,12 +2,44 @@ set -e -if [ "$#" -ne 1 ]; then - echo "Usage: $0 " +# Default values +INPUT="" +OUTPUT_DIR="." +SHEET="Genesis Allocation" + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -i|--input) + INPUT="$2" + shift 2 + ;; + -d|--dir) + OUTPUT_DIR="$2" + shift 2 + ;; + -s|--sheet) + SHEET="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + echo "Usage: $0 -i|--input [-d|--dir ] [-s|--sheet ]" + exit 1 + ;; + esac +done + +# Check if input is provided +if [ -z "$INPUT" ]; then + echo "Error: Input URL or path is required" + echo "Usage: $0 -i|--input [-d|--dir ] [-s|--sheet ]" exit 1 fi -sheet_url="$1" +# Create output directory if it doesn't exist +mkdir -p "$OUTPUT_DIR" + venv_dir="$PWD/venv-lps-lock" script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -21,7 +53,10 @@ fi "$venv_dir/bin/pip" install requests pandas openpyxl echo "Running LPS lock generation script..." -"$venv_dir/bin/python" "$script_dir/generate-lps-distribution-json.py" "$sheet_url" +"$venv_dir/bin/python" "$script_dir/generate-lps-distribution-json.py" \ + --input "$INPUT" \ + --output "$OUTPUT_DIR/distribution.json" \ + --sheet "$SHEET" # Clean up venv echo "Cleaning up..." -- 2.45.2 From 7292d97674bf8035c2e0b4572e8b1e311dd1b40e Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 12:02:18 +0530 Subject: [PATCH 06/11] Update command in README --- docs/run-first-validator.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/run-first-validator.md b/docs/run-first-validator.md index 65cba46..241ab6b 100644 --- a/docs/run-first-validator.md +++ b/docs/run-first-validator.md @@ -48,8 +48,14 @@ - Generate LPS lockup distribution JSON file - ``` - ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh "" + ```bash + # -i, --input: Google Sheet URL or local Excel file path (required) + # -d, --dir: Destination folder for the generated distribution.json file (optional, defaults to current directory) + # -s, --sheet: Sheet name to read (optional, defaults to "Genesis Allocation") + ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh \ + -i "" \ + -d "" \ + -s "" ``` - This will generate the `distribution.json` file at `~/cerc/laconicd-stack/distribution.json` -- 2.45.2 From 0be9dd8f90d025eb3b508828b7140f5b51ee7659 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 12:38:12 +0530 Subject: [PATCH 07/11] Skip invalid entries --- scripts/generate-lps-distribution-json.py | 8 ++++++++ scripts/generate-lps-lock.sh | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py index 792afeb..ba78dcd 100644 --- a/scripts/generate-lps-distribution-json.py +++ b/scripts/generate-lps-distribution-json.py @@ -4,6 +4,7 @@ import pandas as pd import json import re import argparse +from bech32 import bech32_decode def get_excel_download_url(google_sheet_url): """ @@ -57,6 +58,13 @@ def convert_excel_to_json(excel_path, json_path, sheet_name): if not key or key.lower() == 'nan': continue + # If key is the laconic address, validate that it's a valid bech32 address + if key == laconic_address: + hrp, data = bech32_decode(laconic_address) + if hrp is None or data is None or not hrp.startswith("laconic"): + print(f"Skipping invalid Laconic address: {laconic_address}") + continue + entry = { 'total_lps_allocation': row['Total LPS Allocation'] if not pd.isna(row['Total LPS Allocation']) else None, 'lock_months': row['Lock (months)'] if not pd.isna(row['Lock (months)']) else None, diff --git a/scripts/generate-lps-lock.sh b/scripts/generate-lps-lock.sh index 72c6936..fc3c7a3 100755 --- a/scripts/generate-lps-lock.sh +++ b/scripts/generate-lps-lock.sh @@ -50,7 +50,7 @@ fi # Activate venv and install dependencies "$venv_dir/bin/pip" install --upgrade pip -"$venv_dir/bin/pip" install requests pandas openpyxl +"$venv_dir/bin/pip" install requests pandas openpyxl bech32 echo "Running LPS lock generation script..." "$venv_dir/bin/python" "$script_dir/generate-lps-distribution-json.py" \ -- 2.45.2 From 3f0ccc62442dfa1acdf13194bf5805b5a1b202c2 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 18:02:08 +0530 Subject: [PATCH 08/11] Accept csv files instead of xlsx --- csvAllocation.csv | 89 +++++ data/distribution.json | 404 ++++++++++++++++++++++ scripts/generate-lps-distribution-json.py | 64 ++-- 3 files changed, 530 insertions(+), 27 deletions(-) create mode 100644 csvAllocation.csv create mode 100644 data/distribution.json diff --git a/csvAllocation.csv b/csvAllocation.csv new file mode 100644 index 0000000..b768d93 --- /dev/null +++ b/csvAllocation.csv @@ -0,0 +1,89 @@ +Category/Group,Placeholder,Entity,Email,Laconic Address,Total LPS Allocation,Percent Allocation,Lock (months),Vest (months),Multisig?,Testnet 1 Allocation,Testnet 2 Allocation,SLA Allocation +,,,,,,,,,,,, +Seed Investors,,,,,20801,16.05%,,,,,, +,Seed Investor 1,Atomic Form,,foundation1,6480,5%,12,,Yes,,, +,Seed Investor 2,Incredulous,,foundation1,6480,5%,12,,Yes,,, +,Seed Investor 3,Lemniscap,,foundation1,6480,5%,12,,Yes,,, +,Seed Investor 4,Chris H.,,foundation1,1361,1.05%,6,,,,, +,,,,,,,,,,,, +Laconic Ltd,,,,,,,,,,,, +,Team,Eleusian,,ltd1,25920,20%,,36,Yes,,, +,,,,,,,,,,,, +Early Supporters,,,,,,,,,,,, +,For sale,Foundation,,foundation2,,18.95%,,,,,, +,,,,,,,,,,,, +Community Pool,,,,,,,,,,,, +,Community Module,N/A,,autogenerated,38880,30%,,,,,, +,,,,,,,,,,,, +Non-testnet Service Providers,,,,,6480,5%,,,,,, +,Autonomous,,,TBD,,0.10%,,,,,, +,Mito,ZACHARY RAMSAY,,TBD,,,,,,,, +,Owen,,,TBD,,,,,,,, +,Mark,,,TBD,,,,,,,, +,Zee,,,TBD,,,,,,,, +,Remainder (marketing),Foundation,,foundation3,TBD,,,,Yes,,, +,,,,,,,,,,,, +Testnet,,,,,12960,10%,,,,,, +,Remainder (marketing),Foundation,,foundation3,9863.895212481530000,,,,Yes,,, +Ongoing Service Providers,,,,,,,,,,,bonuses + https://github.com/LaconicNetwork/loro-testnet/pull/60, +,BlackBlocks,EDUARDO WILLIAM HERZOG,info@blackblocks.io,laconic128vt4we3s044zycwydz9f6amzrlp7r6lnputdg,437.568163257075000,,,,,169.568163257075000,100,168 +,rxpwnz,DENISS VASILENKO,paladinlolwto@gmail.com,laconic19h70dln5ktxpc8mcam5nm22glr7h9qtlzvvrtq,366.236759056674000,,,,,98.236759056674200,100,168 +,MekongLabs,NGUYỄN THỂ NGUYÊN,nguyen@mekonglabs.tech,laconic195s2w429xuxqagkz54n55dcpfz4nwl0k62qnet,347.478327502243000,,,,,79.478327502243400,100,168 +,Silent,LYU PENG,silentvalidator@gmail.com,laconic1256aqyag45x84usd6xj053musfcql74j4j3ll3,143.558393240641000,,,,,118.558393240641000,25,0 +,Barg Systems,BRANDON YOUNG,beezy@barg.systems,laconic1mjzrgc8ucspjz98g76c8pce026l5newrujetx0,152.988072312237000,,,,,102.988072312237000,50,0 +,Dream Gallery,HUI ZHAO,infinite.virtual.reality.43@gmail.com,laconic1f9j8n9rqsekzp0rffe3298pytms4hfz20khge3,117.107359272441000,,,,,92.107359272441300,25,0 +,,,,,,,,,,,, +Testnet 2 Bonus Service Providers,Ellipfra,MARC-ANDRE DUMAS,ma@ellipfra.com,laconic1axg567nvu92un33z6z547n7klkeq6ud37pwz35,114.304453473952000,,,,,104.304453473952000,10,0 +,High Stakes,THOMAS CHRISTOPHE LAFAILLE,contact@highstakes.ch,laconic1vy8tnar3w7zxusnwhp5jdzw97rusr2d6n8ch5c,83.616317641483800,,,,,73.616317641483800,10,0 +,Cosmos Spaces,TBD,mrtn.ogrady@gmail.com,laconic1qsvrehuchjquanwm7gsx7cvze8t959l7zf0zpw,21.097359439554500,,,,,16.097359439554500,5,0 +,,,,,,,,,,,, +Testnet 1 (only) Service Providers,,,,,,,,,,,, +,Hypha,Lexa,,laconic1s03twj8fedmcn04kzt2z35mwy34e7hxnm423sh,161.45,,,,,161.45,0,0 +,KenZ,QUANG TUYEN TRAN,quangtuyenpdu@gmail.com,laconic16v0lazxvmccs0893g58fqa65m6344dlcpxrvs0,103.440578336577000,,,,,103.440578336577000,0,0 +,spidey,ASHISH SHARMA,andyroddick6600@gmail.com,laconic1a2h0eck0dra2fu9xcama9rrygncjc30ex35ly5,101.548280416612000,,,,,101.548280416612000,0,0 +,Wavefive,JAMES JOSEPH COUSINS,jim@wavefive.co,laconic1dx3jyjfpcwdwufj5uuufk84f5ugm5h4wf3jsl2,93.279761244593200,,,,,93.279761244593200,0,0 +,DragonZ,XUAN HUAN NGUYEN,kenz4788@gmail.com,laconic1f7tursd29yrk3mnys3javqngraj5ls7k5h3vvv,84.167935390851100,,,,,84.167935390851100,0,0 +,yandc,DECHEN YAN,dechenyan@gmail.com,laconic14vzrlac5zte5nju9fm0ktzfz7e4zss74f6lpzx,81.103235498734600,,,,,81.103235498734600,0,0 +,CalvinJoe,KOSTIANTYN KONSTANTINOV,dvadcatodinpilot@hotmail.com,laconic1nmuxuz3z2xj5fqf2sz5nn0u2r2al7mutsl8pm7,76.681017533600200,,,,,76.681017533600200,0,0 +,Nodeify,VINCENT PETOSCIA,vince@nodeify.net,laconic18uc9h349nd0w62vnleu8ywu3sur7ly0kdsgmg3,75.488047105796500,,,,,75.488047105796500,0,0 +,Twaltoner,VALERIIA IVANENKO,aciessnull@hotmail.com,laconic1360txwdlk4z0604vd22dcarxt9w3ddj8d8mz8m,74.870993436242800,,,,,74.870993436242800,0,0 +,AndreasV,VALERIIA MIKAELIAN,mohadeseshakiba3@gmail.com,laconic1wrwl5557yxgqkwq4djlrz33x5nd5f0j9vh42jg,74.634456196247300,,,,,74.634456196247300,0,0 +,Elf,ZIQI ZHANG,zzq8556489@outlook.com,laconic1ka6xtcejersljsmslc6tw9uxvfmans476v98r0,73.194664300622100,,,,,73.194664300622100,0,0 +,twelly8,VITALII HRYNOV,tanousbronella@gmail.com,laconic1ljwtpta6xfgtnk0e03h4t77chjygv399pr6utz,73.122674705840800,,,,,73.122674705840800,0,0 +,Quitlantarah,LARYSA GVOZDARYOVA,soulynhaphommalangsy@gmail.com,laconic1vfs90x57ufs87tn9h6zs3xylnzh97f03qy0ggz,73.040400883233700,,,,,73.040400883233700,0,0 +,,,,,,,,,,,, +Testnet 1 App Publishers,,,,,,,,,,,, +,,SEBASTIAN VOUTAT,info@swiss-staking.ch,laconic1qw26grwct7xtjdrlseurh9v6g8wu2x3vded63g,15.744925453565700,,,,,,, +,,Nguyễn Thị Thu Phương,choioff@gmail.com,laconic1r70vhqwvf7dw2twy6m77f34fzeshp9fqxtxace,11.594036285252400,,,,,,, +,,TRỊNH NGỌC ĐOAN,trinhdoanqh@gmail.com,laconic1nezjpcfflf8nc5yt2hx5yd20ry6ka066tth38w,11.594036285252400,,,,,,, +,,VADYM KUSHNIR,88vgk88@gmail.com,laconic1xwwy9944lgu3djvgmk4l4x59x5cjzczcxuj9f5,11.378659960481400,,,,,,, +,,DINH DUNG DANG,dangdinhdung@gmail.com,laconic1kkv020aj5z8es9shrylvlcjfextm2srg0085ml,9.831866355308070,,,,,,, +,,PATRICK HOFMEISTER,pathrock@protonmail.com,laconic1qrss36gx7rx58uffn60lx99fr0d929566mpafj,9.831866355308070,,,,,,, +,,Pablo Alexandro Lema Diez de Medina,pablo@nodesoda.com,laconic1g3dugtdlardfg28teljfzftzfeynjheae07ytr,8.265493084246450,,,,,,, +,,Azmy Rachman K,orang3club@gmail.com,laconic1rcssfrp47s0xmg2vahshmf6zcaadqamjel2a7r,6.072570504760190,,,,,,, +,,CHUKWUDALU EMMANUEL IFEDIORA,chukwudaluemmanuel7@gmail.com,laconic1jeylpuu59d4a5qynj8xm99ssgmk7w5w95n6q00,4.153763247709720,,,,,,, +,,VICTOR SOMTOCHUKWU OKOLI,foroncecomeandseeme@gmail.com,laconic17njvfpqxv6nc6ky5yvkk5g2r35tlvkqk4x0as9,4.153763247709720,,,,,,, +,,CHINEDU ANTHONY AGUDE,dalupython@gmail.com,laconic1hw5vr47nl4876nd728vcy4m44j57un67guldlv,4.153763247709720,,,,,,, +,,ABUCHI COLUMBUS NDIBE,dyingifeellike@gmail.com,laconic1nthmxgdtf58mntuukz4r5v0ry6zctl2ve9aqpe,4.153763247709720,,,,,,, +,,WISDOM CHUKWUBUIKEM NWAUBANI,chimdioligarchy@gmail.com,laconic17zcxj4fyaef42da7pk0ccqxz2a8fns5fxs2qlr,4.153763247709720,,,,,,, +,,Azeez Adebowale Adekanbi,kentmererashida@gmail.com,laconic1l7tc37faxf9knl9rxmkfzc26dchnrtzvderurf,4.153763247709720,,,,,,, +,,Ikenna Ozigbo,shareladyboss@gmail.com,laconic1aahpp8vknsq72vamrfgnn86m4ple5xqnd5dydz,4.153763247709720,,,,,,, +,,VICTOR EZECHUKWU NZENWA,pushinmoni@gmail.com,laconic12wrfzczt0qgknjv9nle4uczujpqxrkj7p4v9uj,4.153763247709720,,,,,,, +,,IFEANYI EMMANUEL EJIM,eejim399@gmail.com,laconic1z3syuquq0gdhvhtjs75lcsrpplm79ycxjtdge6,3.957966588827020,,,,,,, +,,Charles Ekeigbo,preciousuwem83@gmail.com,laconic122mal2jwd9x2vfxrpxtd9vdz85ksggeq0tlle5,3.957966588827020,,,,,,, +,,CHIMEZIE CHRISTOPHER IFEDIORA,ethskytrixsmartcontract@gmail.com,laconic15y76s0ml2dfzef3y07x6hmcngtcaw59d8y2sls,3.605532602838150,,,,,,, +,,TARAS GRUZHEVSKIY,office@noders.team,laconic1yavpc0fjk3ze33kfuuc5fra5x3nzs20ajhpef5,3.292257948625830,,,,,,, +,,Olusola Adebesin,olusolaadebesin0@gmail.com,laconic1qzwl52vns3gecngsh59y5yvg9a8m345dz2qv8x,3.292257948625830,,,,,,, +,,ENIOLA OLUWAFEMI OLATUNDE,olatenny@gmail.com,laconic1nr6z78gkf6swk9m02qtdazde7jr9csetv402wr,2.783186635530810,,,,,,, +,,DANIEL OLUMIDE OLATUNDE,reabumble@gmail.com,laconic17uukytqarpu6wsmjcqgfcs2tjhwhfu6eq72cpw,2.783186635530810,,,,,,, +,,OLUWASEUN JOSEPH-AYOTUNDE OLATUNDE,ecares4mee@gmail.com,laconic17g9ytaauphqv5lawthk2hj9n04eardz28yvnfk,2.783186635530810,,,,,,, +,,Temiloluwa Olasiwale,enny4wise@gmail.com,laconic16pxr8lupfcswatynedc76ynw5f74jpcmjt28vs,2.783186635530810,,,,,,, +,,David Akinyemi,f333miola@gmail.com,laconic1xnvd8fdr5zwfa2thdlr2pg22ndg4e0dptqfav9,2.783186635530810,,,,,,, +,,JUWON SIMON OLATUNDE,enny4bea@gmail.com,laconic1qykx88yyy3a6udmqfu3aej40rymklnynfr5cq8,2.783186635530810,,,,,,, +,,JULIET CHINECHEREM OKEIFUFE,richardjuliet1996@gmail.com,laconic1qjjvdwlt2u5cgmaxn6l66nwnqw9fs4vl7g045h,2.783186635530810,,,,,,, +,,OLUWATOBI DANIEL OLAYANJU,barthenry41@gmail.com,laconic1mdzgqw7re2fuws0uycpm90nt07d6ntsk5alt4j,2.783186635530810,,,,,,, +,,IFEOLUWA JOSEPH ADELABU,danieelleexx@gmail.com,laconic157jy998f0x2m0kms8r6mmfs3zazljpd0svd9ne,2.783186635530810,,,,,,, +,,EMEKA OBI,kobi6542@gmail.com,laconic1rdtz32xsgw7yrjfrue36pglevpymc5aflu4cfy,2.783186635530810,,,,,,, +,,Vladimir Skopintsev,posthuman.validator@gmail.com,laconic14dzwrzdfgln6z2vuu0jncvwjt2l7e4yl7slmjq,2.646128974312920,,,,,,, +,,,,,,,,,,,, +,,,,Total testnet allocation,3096.104787518470000,,,,,,, \ No newline at end of file diff --git a/data/distribution.json b/data/distribution.json new file mode 100644 index 0000000..aa4ed23 --- /dev/null +++ b/data/distribution.json @@ -0,0 +1,404 @@ +{ + "Seed Investor 1": { + "total_lps_allocation": 6480.0, + "lock_months": 12.0, + "vest_months": null, + "laconic_address": "foundation1" + }, + "Seed Investor 2": { + "total_lps_allocation": 6480.0, + "lock_months": 12.0, + "vest_months": null, + "laconic_address": "foundation1" + }, + "Seed Investor 3": { + "total_lps_allocation": 6480.0, + "lock_months": 12.0, + "vest_months": null, + "laconic_address": "foundation1" + }, + "Seed Investor 4": { + "total_lps_allocation": 1361.0, + "lock_months": 6.0, + "vest_months": null, + "laconic_address": "foundation1" + }, + "Team": { + "total_lps_allocation": 25920.0, + "lock_months": null, + "vest_months": 36.0, + "laconic_address": "ltd1" + }, + "For sale": { + "total_lps_allocation": null, + "lock_months": null, + "vest_months": null, + "laconic_address": "foundation2" + }, + "Community Module": { + "total_lps_allocation": 38880.0, + "lock_months": null, + "vest_months": null, + "laconic_address": "autogenerated" + }, + "Autonomous": { + "total_lps_allocation": null, + "lock_months": null, + "vest_months": null, + "laconic_address": "TBD" + }, + "Mito": { + "total_lps_allocation": null, + "lock_months": null, + "vest_months": null, + "laconic_address": "TBD" + }, + "Owen": { + "total_lps_allocation": null, + "lock_months": null, + "vest_months": null, + "laconic_address": "TBD" + }, + "Mark": { + "total_lps_allocation": null, + "lock_months": null, + "vest_months": null, + "laconic_address": "TBD" + }, + "Zee": { + "total_lps_allocation": null, + "lock_months": null, + "vest_months": null, + "laconic_address": "TBD" + }, + "Remainder (marketing)": { + "total_lps_allocation": 9863.89521248153, + "lock_months": null, + "vest_months": null, + "laconic_address": "foundation3" + }, + "BlackBlocks": { + "total_lps_allocation": 437.568163257075, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic128vt4we3s044zycwydz9f6amzrlp7r6lnputdg" + }, + "rxpwnz": { + "total_lps_allocation": 366.236759056674, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic19h70dln5ktxpc8mcam5nm22glr7h9qtlzvvrtq" + }, + "MekongLabs": { + "total_lps_allocation": 347.478327502243, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic195s2w429xuxqagkz54n55dcpfz4nwl0k62qnet" + }, + "Silent": { + "total_lps_allocation": 143.558393240641, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1256aqyag45x84usd6xj053musfcql74j4j3ll3" + }, + "Barg Systems": { + "total_lps_allocation": 152.988072312237, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1mjzrgc8ucspjz98g76c8pce026l5newrujetx0" + }, + "Dream Gallery": { + "total_lps_allocation": 117.107359272441, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1f9j8n9rqsekzp0rffe3298pytms4hfz20khge3" + }, + "Ellipfra": { + "total_lps_allocation": 114.304453473952, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1axg567nvu92un33z6z547n7klkeq6ud37pwz35" + }, + "High Stakes": { + "total_lps_allocation": 83.6163176414838, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1vy8tnar3w7zxusnwhp5jdzw97rusr2d6n8ch5c" + }, + "Cosmos Spaces": { + "total_lps_allocation": 21.0973594395545, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1qsvrehuchjquanwm7gsx7cvze8t959l7zf0zpw" + }, + "Hypha": { + "total_lps_allocation": 161.45, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1s03twj8fedmcn04kzt2z35mwy34e7hxnm423sh" + }, + "KenZ": { + "total_lps_allocation": 103.440578336577, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic16v0lazxvmccs0893g58fqa65m6344dlcpxrvs0" + }, + "spidey": { + "total_lps_allocation": 101.548280416612, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1a2h0eck0dra2fu9xcama9rrygncjc30ex35ly5" + }, + "Wavefive": { + "total_lps_allocation": 93.2797612445932, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1dx3jyjfpcwdwufj5uuufk84f5ugm5h4wf3jsl2" + }, + "DragonZ": { + "total_lps_allocation": 84.1679353908511, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1f7tursd29yrk3mnys3javqngraj5ls7k5h3vvv" + }, + "yandc": { + "total_lps_allocation": 81.1032354987346, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic14vzrlac5zte5nju9fm0ktzfz7e4zss74f6lpzx" + }, + "CalvinJoe": { + "total_lps_allocation": 76.6810175336002, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1nmuxuz3z2xj5fqf2sz5nn0u2r2al7mutsl8pm7" + }, + "Nodeify": { + "total_lps_allocation": 75.4880471057965, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic18uc9h349nd0w62vnleu8ywu3sur7ly0kdsgmg3" + }, + "Twaltoner": { + "total_lps_allocation": 74.8709934362428, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1360txwdlk4z0604vd22dcarxt9w3ddj8d8mz8m" + }, + "AndreasV": { + "total_lps_allocation": 74.6344561962473, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1wrwl5557yxgqkwq4djlrz33x5nd5f0j9vh42jg" + }, + "Elf": { + "total_lps_allocation": 73.1946643006221, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1ka6xtcejersljsmslc6tw9uxvfmans476v98r0" + }, + "twelly8": { + "total_lps_allocation": 73.1226747058408, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1ljwtpta6xfgtnk0e03h4t77chjygv399pr6utz" + }, + "Quitlantarah": { + "total_lps_allocation": 73.0404008832337, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1vfs90x57ufs87tn9h6zs3xylnzh97f03qy0ggz" + }, + "laconic1qw26grwct7xtjdrlseurh9v6g8wu2x3vded63g": { + "total_lps_allocation": 15.7449254535657, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1qw26grwct7xtjdrlseurh9v6g8wu2x3vded63g" + }, + "laconic1r70vhqwvf7dw2twy6m77f34fzeshp9fqxtxace": { + "total_lps_allocation": 11.5940362852524, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1r70vhqwvf7dw2twy6m77f34fzeshp9fqxtxace" + }, + "laconic1nezjpcfflf8nc5yt2hx5yd20ry6ka066tth38w": { + "total_lps_allocation": 11.5940362852524, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1nezjpcfflf8nc5yt2hx5yd20ry6ka066tth38w" + }, + "laconic1xwwy9944lgu3djvgmk4l4x59x5cjzczcxuj9f5": { + "total_lps_allocation": 11.3786599604814, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1xwwy9944lgu3djvgmk4l4x59x5cjzczcxuj9f5" + }, + "laconic1kkv020aj5z8es9shrylvlcjfextm2srg0085ml": { + "total_lps_allocation": 9.83186635530807, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1kkv020aj5z8es9shrylvlcjfextm2srg0085ml" + }, + "laconic1qrss36gx7rx58uffn60lx99fr0d929566mpafj": { + "total_lps_allocation": 9.83186635530807, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1qrss36gx7rx58uffn60lx99fr0d929566mpafj" + }, + "laconic1g3dugtdlardfg28teljfzftzfeynjheae07ytr": { + "total_lps_allocation": 8.26549308424645, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1g3dugtdlardfg28teljfzftzfeynjheae07ytr" + }, + "laconic1rcssfrp47s0xmg2vahshmf6zcaadqamjel2a7r": { + "total_lps_allocation": 6.07257050476019, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1rcssfrp47s0xmg2vahshmf6zcaadqamjel2a7r" + }, + "laconic1jeylpuu59d4a5qynj8xm99ssgmk7w5w95n6q00": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1jeylpuu59d4a5qynj8xm99ssgmk7w5w95n6q00" + }, + "laconic17njvfpqxv6nc6ky5yvkk5g2r35tlvkqk4x0as9": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic17njvfpqxv6nc6ky5yvkk5g2r35tlvkqk4x0as9" + }, + "laconic1hw5vr47nl4876nd728vcy4m44j57un67guldlv": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1hw5vr47nl4876nd728vcy4m44j57un67guldlv" + }, + "laconic1nthmxgdtf58mntuukz4r5v0ry6zctl2ve9aqpe": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1nthmxgdtf58mntuukz4r5v0ry6zctl2ve9aqpe" + }, + "laconic17zcxj4fyaef42da7pk0ccqxz2a8fns5fxs2qlr": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic17zcxj4fyaef42da7pk0ccqxz2a8fns5fxs2qlr" + }, + "laconic1l7tc37faxf9knl9rxmkfzc26dchnrtzvderurf": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1l7tc37faxf9knl9rxmkfzc26dchnrtzvderurf" + }, + "laconic1aahpp8vknsq72vamrfgnn86m4ple5xqnd5dydz": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1aahpp8vknsq72vamrfgnn86m4ple5xqnd5dydz" + }, + "laconic12wrfzczt0qgknjv9nle4uczujpqxrkj7p4v9uj": { + "total_lps_allocation": 4.15376324770972, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic12wrfzczt0qgknjv9nle4uczujpqxrkj7p4v9uj" + }, + "laconic1z3syuquq0gdhvhtjs75lcsrpplm79ycxjtdge6": { + "total_lps_allocation": 3.95796658882702, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1z3syuquq0gdhvhtjs75lcsrpplm79ycxjtdge6" + }, + "laconic122mal2jwd9x2vfxrpxtd9vdz85ksggeq0tlle5": { + "total_lps_allocation": 3.95796658882702, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic122mal2jwd9x2vfxrpxtd9vdz85ksggeq0tlle5" + }, + "laconic15y76s0ml2dfzef3y07x6hmcngtcaw59d8y2sls": { + "total_lps_allocation": 3.60553260283815, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic15y76s0ml2dfzef3y07x6hmcngtcaw59d8y2sls" + }, + "laconic1yavpc0fjk3ze33kfuuc5fra5x3nzs20ajhpef5": { + "total_lps_allocation": 3.29225794862583, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1yavpc0fjk3ze33kfuuc5fra5x3nzs20ajhpef5" + }, + "laconic1qzwl52vns3gecngsh59y5yvg9a8m345dz2qv8x": { + "total_lps_allocation": 3.29225794862583, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1qzwl52vns3gecngsh59y5yvg9a8m345dz2qv8x" + }, + "laconic1nr6z78gkf6swk9m02qtdazde7jr9csetv402wr": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1nr6z78gkf6swk9m02qtdazde7jr9csetv402wr" + }, + "laconic17uukytqarpu6wsmjcqgfcs2tjhwhfu6eq72cpw": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic17uukytqarpu6wsmjcqgfcs2tjhwhfu6eq72cpw" + }, + "laconic17g9ytaauphqv5lawthk2hj9n04eardz28yvnfk": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic17g9ytaauphqv5lawthk2hj9n04eardz28yvnfk" + }, + "laconic16pxr8lupfcswatynedc76ynw5f74jpcmjt28vs": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic16pxr8lupfcswatynedc76ynw5f74jpcmjt28vs" + }, + "laconic1xnvd8fdr5zwfa2thdlr2pg22ndg4e0dptqfav9": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1xnvd8fdr5zwfa2thdlr2pg22ndg4e0dptqfav9" + }, + "laconic1qykx88yyy3a6udmqfu3aej40rymklnynfr5cq8": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1qykx88yyy3a6udmqfu3aej40rymklnynfr5cq8" + }, + "laconic1qjjvdwlt2u5cgmaxn6l66nwnqw9fs4vl7g045h": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1qjjvdwlt2u5cgmaxn6l66nwnqw9fs4vl7g045h" + }, + "laconic1mdzgqw7re2fuws0uycpm90nt07d6ntsk5alt4j": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1mdzgqw7re2fuws0uycpm90nt07d6ntsk5alt4j" + }, + "laconic157jy998f0x2m0kms8r6mmfs3zazljpd0svd9ne": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic157jy998f0x2m0kms8r6mmfs3zazljpd0svd9ne" + }, + "laconic1rdtz32xsgw7yrjfrue36pglevpymc5aflu4cfy": { + "total_lps_allocation": 2.78318663553081, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic1rdtz32xsgw7yrjfrue36pglevpymc5aflu4cfy" + }, + "laconic14dzwrzdfgln6z2vuu0jncvwjt2l7e4yl7slmjq": { + "total_lps_allocation": 2.64612897431292, + "lock_months": null, + "vest_months": null, + "laconic_address": "laconic14dzwrzdfgln6z2vuu0jncvwjt2l7e4yl7slmjq" + } +} \ No newline at end of file diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py index ba78dcd..fc4cfbe 100644 --- a/scripts/generate-lps-distribution-json.py +++ b/scripts/generate-lps-distribution-json.py @@ -4,23 +4,31 @@ import pandas as pd import json import re import argparse +import urllib.parse from bech32 import bech32_decode -def get_excel_download_url(google_sheet_url): +def get_csv_download_url(google_sheet_url): """ - Convert a Google Sheets URL to its Excel export URL. + Convert a full Google Sheets URL to a CSV export URL using the `gid` in the query string. """ - # Extract the Sheet ID to construct the download URL + # Extract the sheet ID match = re.search(r'/d/([a-zA-Z0-9-_]+)', google_sheet_url) if not match: raise ValueError('Invalid Google Sheets URL') sheet_id = match.group(1) - # Export the entire spreadsheet as an Excel file (includes all sheets) - return f'https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=xlsx&id={sheet_id}' -def download_excel(url, output_path): + # Extract gid from query params + gid_match = re.search(r'[?&]gid=([0-9]+)', google_sheet_url) + if not gid_match: + raise ValueError('Missing gid in Google Sheets URL') + gid = gid_match.group(1) + + # Build export URL + return f'https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv&gid={gid}' + +def download_csv(url, output_path): """ - Download the Excel file from the given URL. + Download the CSV file from the given URL. """ response = requests.get(url) if response.status_code != 200: @@ -28,12 +36,11 @@ def download_excel(url, output_path): with open(output_path, 'wb') as f: f.write(response.content) -def convert_excel_to_json(excel_path, json_path, sheet_name): +def convert_csv_to_json(csv_path, json_path): """ - Read the Excel file, extract columns from the specified sheet, and save as JSON. + Read the CSV file, extract columns, and save as JSON. """ - df = pd.read_excel(excel_path, sheet_name=sheet_name) - # Ensure columns exist + df = pd.read_csv(csv_path) required_columns = [ 'Placeholder', 'Laconic Address', @@ -48,25 +55,28 @@ def convert_excel_to_json(excel_path, json_path, sheet_name): result = {} for _, row in df.iterrows(): placeholder = str(row['Placeholder']) if not pd.isna(row['Placeholder']) else '' - laconic_address = str(row['Laconic Address']) if not pd.isna(row['Laconic Address']) else '' - - # Use laconic_address as key if placeholder is missing or empty key = placeholder if placeholder and placeholder.lower() != 'nan' else laconic_address - # Skip the row if both 'Placeholder' and 'Laconic Address' are missing or invalid if not key or key.lower() == 'nan': continue - # If key is the laconic address, validate that it's a valid bech32 address if key == laconic_address: hrp, data = bech32_decode(laconic_address) if hrp is None or data is None or not hrp.startswith("laconic"): print(f"Skipping invalid Laconic address: {laconic_address}") continue + def to_number(val): + if pd.isna(val) or str(val).strip() == '': + return None + try: + return float(val) + except (ValueError, TypeError): + return None + entry = { - 'total_lps_allocation': row['Total LPS Allocation'] if not pd.isna(row['Total LPS Allocation']) else None, + 'total_lps_allocation': to_number(row['Total LPS Allocation']), 'lock_months': row['Lock (months)'] if not pd.isna(row['Lock (months)']) else None, 'vest_months': row['Vest (months)'] if not pd.isna(row['Vest (months)']) else None, 'laconic_address': row['Laconic Address'] if not pd.isna(row['Laconic Address']) else None @@ -78,24 +88,24 @@ def convert_excel_to_json(excel_path, json_path, sheet_name): json.dump(result, f, indent=2) def main(): - parser = argparse.ArgumentParser(description='Generate LPS distribution JSON from Excel or Google Sheet') - parser.add_argument('--input', '-i', required=True, help='Input: Google Sheet URL or local Excel file path') + parser = argparse.ArgumentParser(description='Generate LPS distribution JSON from CSV or Google Sheet') + parser.add_argument('--input', '-i', required=True, help='Input: Google Sheet URL or local CSV file path') parser.add_argument('--output', '-o', default='distribution.json', help='Output JSON file path (default: distribution.json)') parser.add_argument('--sheet', '-s', default='Genesis Allocation', help='Sheet name to read (default: Genesis Allocation)') args = parser.parse_args() if args.input.startswith('https://'): - excel_url = get_excel_download_url(args.input) - excel_path = 'sheet.xlsx' - print(f'Downloading Excel file from: {excel_url}') - download_excel(excel_url, excel_path) + csv_url = get_csv_download_url(args.input) + csv_path = 'sheet.csv' + print(f'Downloading CSV file from: {csv_url}') + download_csv(csv_url, csv_path) else: - excel_path = args.input - print(f'Using Excel file at path: {excel_path}') + csv_path = args.input + print(f'Using CSV file at path: {csv_path}') - print(f'Converting Excel to JSON (sheet: {args.sheet})...') - convert_excel_to_json(excel_path, args.output, args.sheet) + print('Converting CSV to JSON...') + convert_csv_to_json(csv_path, args.output) print(f'JSON saved to {args.output}') if __name__ == '__main__': -- 2.45.2 From 1bca048577f5feededfd23637efda1478c21aaf1 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 18:02:57 +0530 Subject: [PATCH 09/11] Remove unnecessary argument --- csvAllocation.csv | 89 ----- data/distribution.json | 404 ---------------------- docs/run-first-validator.md | 12 +- scripts/generate-lps-distribution-json.py | 6 +- scripts/generate-lps-lock.sh | 12 +- 5 files changed, 11 insertions(+), 512 deletions(-) delete mode 100644 csvAllocation.csv delete mode 100644 data/distribution.json diff --git a/csvAllocation.csv b/csvAllocation.csv deleted file mode 100644 index b768d93..0000000 --- a/csvAllocation.csv +++ /dev/null @@ -1,89 +0,0 @@ -Category/Group,Placeholder,Entity,Email,Laconic Address,Total LPS Allocation,Percent Allocation,Lock (months),Vest (months),Multisig?,Testnet 1 Allocation,Testnet 2 Allocation,SLA Allocation -,,,,,,,,,,,, -Seed Investors,,,,,20801,16.05%,,,,,, -,Seed Investor 1,Atomic Form,,foundation1,6480,5%,12,,Yes,,, -,Seed Investor 2,Incredulous,,foundation1,6480,5%,12,,Yes,,, -,Seed Investor 3,Lemniscap,,foundation1,6480,5%,12,,Yes,,, -,Seed Investor 4,Chris H.,,foundation1,1361,1.05%,6,,,,, -,,,,,,,,,,,, -Laconic Ltd,,,,,,,,,,,, -,Team,Eleusian,,ltd1,25920,20%,,36,Yes,,, -,,,,,,,,,,,, -Early Supporters,,,,,,,,,,,, -,For sale,Foundation,,foundation2,,18.95%,,,,,, -,,,,,,,,,,,, -Community Pool,,,,,,,,,,,, -,Community Module,N/A,,autogenerated,38880,30%,,,,,, -,,,,,,,,,,,, -Non-testnet Service Providers,,,,,6480,5%,,,,,, -,Autonomous,,,TBD,,0.10%,,,,,, -,Mito,ZACHARY RAMSAY,,TBD,,,,,,,, -,Owen,,,TBD,,,,,,,, -,Mark,,,TBD,,,,,,,, -,Zee,,,TBD,,,,,,,, -,Remainder (marketing),Foundation,,foundation3,TBD,,,,Yes,,, -,,,,,,,,,,,, -Testnet,,,,,12960,10%,,,,,, -,Remainder (marketing),Foundation,,foundation3,9863.895212481530000,,,,Yes,,, -Ongoing Service Providers,,,,,,,,,,,bonuses + https://github.com/LaconicNetwork/loro-testnet/pull/60, -,BlackBlocks,EDUARDO WILLIAM HERZOG,info@blackblocks.io,laconic128vt4we3s044zycwydz9f6amzrlp7r6lnputdg,437.568163257075000,,,,,169.568163257075000,100,168 -,rxpwnz,DENISS VASILENKO,paladinlolwto@gmail.com,laconic19h70dln5ktxpc8mcam5nm22glr7h9qtlzvvrtq,366.236759056674000,,,,,98.236759056674200,100,168 -,MekongLabs,NGUYỄN THỂ NGUYÊN,nguyen@mekonglabs.tech,laconic195s2w429xuxqagkz54n55dcpfz4nwl0k62qnet,347.478327502243000,,,,,79.478327502243400,100,168 -,Silent,LYU PENG,silentvalidator@gmail.com,laconic1256aqyag45x84usd6xj053musfcql74j4j3ll3,143.558393240641000,,,,,118.558393240641000,25,0 -,Barg Systems,BRANDON YOUNG,beezy@barg.systems,laconic1mjzrgc8ucspjz98g76c8pce026l5newrujetx0,152.988072312237000,,,,,102.988072312237000,50,0 -,Dream Gallery,HUI ZHAO,infinite.virtual.reality.43@gmail.com,laconic1f9j8n9rqsekzp0rffe3298pytms4hfz20khge3,117.107359272441000,,,,,92.107359272441300,25,0 -,,,,,,,,,,,, -Testnet 2 Bonus Service Providers,Ellipfra,MARC-ANDRE DUMAS,ma@ellipfra.com,laconic1axg567nvu92un33z6z547n7klkeq6ud37pwz35,114.304453473952000,,,,,104.304453473952000,10,0 -,High Stakes,THOMAS CHRISTOPHE LAFAILLE,contact@highstakes.ch,laconic1vy8tnar3w7zxusnwhp5jdzw97rusr2d6n8ch5c,83.616317641483800,,,,,73.616317641483800,10,0 -,Cosmos Spaces,TBD,mrtn.ogrady@gmail.com,laconic1qsvrehuchjquanwm7gsx7cvze8t959l7zf0zpw,21.097359439554500,,,,,16.097359439554500,5,0 -,,,,,,,,,,,, -Testnet 1 (only) Service Providers,,,,,,,,,,,, -,Hypha,Lexa,,laconic1s03twj8fedmcn04kzt2z35mwy34e7hxnm423sh,161.45,,,,,161.45,0,0 -,KenZ,QUANG TUYEN TRAN,quangtuyenpdu@gmail.com,laconic16v0lazxvmccs0893g58fqa65m6344dlcpxrvs0,103.440578336577000,,,,,103.440578336577000,0,0 -,spidey,ASHISH SHARMA,andyroddick6600@gmail.com,laconic1a2h0eck0dra2fu9xcama9rrygncjc30ex35ly5,101.548280416612000,,,,,101.548280416612000,0,0 -,Wavefive,JAMES JOSEPH COUSINS,jim@wavefive.co,laconic1dx3jyjfpcwdwufj5uuufk84f5ugm5h4wf3jsl2,93.279761244593200,,,,,93.279761244593200,0,0 -,DragonZ,XUAN HUAN NGUYEN,kenz4788@gmail.com,laconic1f7tursd29yrk3mnys3javqngraj5ls7k5h3vvv,84.167935390851100,,,,,84.167935390851100,0,0 -,yandc,DECHEN YAN,dechenyan@gmail.com,laconic14vzrlac5zte5nju9fm0ktzfz7e4zss74f6lpzx,81.103235498734600,,,,,81.103235498734600,0,0 -,CalvinJoe,KOSTIANTYN KONSTANTINOV,dvadcatodinpilot@hotmail.com,laconic1nmuxuz3z2xj5fqf2sz5nn0u2r2al7mutsl8pm7,76.681017533600200,,,,,76.681017533600200,0,0 -,Nodeify,VINCENT PETOSCIA,vince@nodeify.net,laconic18uc9h349nd0w62vnleu8ywu3sur7ly0kdsgmg3,75.488047105796500,,,,,75.488047105796500,0,0 -,Twaltoner,VALERIIA IVANENKO,aciessnull@hotmail.com,laconic1360txwdlk4z0604vd22dcarxt9w3ddj8d8mz8m,74.870993436242800,,,,,74.870993436242800,0,0 -,AndreasV,VALERIIA MIKAELIAN,mohadeseshakiba3@gmail.com,laconic1wrwl5557yxgqkwq4djlrz33x5nd5f0j9vh42jg,74.634456196247300,,,,,74.634456196247300,0,0 -,Elf,ZIQI ZHANG,zzq8556489@outlook.com,laconic1ka6xtcejersljsmslc6tw9uxvfmans476v98r0,73.194664300622100,,,,,73.194664300622100,0,0 -,twelly8,VITALII HRYNOV,tanousbronella@gmail.com,laconic1ljwtpta6xfgtnk0e03h4t77chjygv399pr6utz,73.122674705840800,,,,,73.122674705840800,0,0 -,Quitlantarah,LARYSA GVOZDARYOVA,soulynhaphommalangsy@gmail.com,laconic1vfs90x57ufs87tn9h6zs3xylnzh97f03qy0ggz,73.040400883233700,,,,,73.040400883233700,0,0 -,,,,,,,,,,,, -Testnet 1 App Publishers,,,,,,,,,,,, -,,SEBASTIAN VOUTAT,info@swiss-staking.ch,laconic1qw26grwct7xtjdrlseurh9v6g8wu2x3vded63g,15.744925453565700,,,,,,, -,,Nguyễn Thị Thu Phương,choioff@gmail.com,laconic1r70vhqwvf7dw2twy6m77f34fzeshp9fqxtxace,11.594036285252400,,,,,,, -,,TRỊNH NGỌC ĐOAN,trinhdoanqh@gmail.com,laconic1nezjpcfflf8nc5yt2hx5yd20ry6ka066tth38w,11.594036285252400,,,,,,, -,,VADYM KUSHNIR,88vgk88@gmail.com,laconic1xwwy9944lgu3djvgmk4l4x59x5cjzczcxuj9f5,11.378659960481400,,,,,,, -,,DINH DUNG DANG,dangdinhdung@gmail.com,laconic1kkv020aj5z8es9shrylvlcjfextm2srg0085ml,9.831866355308070,,,,,,, -,,PATRICK HOFMEISTER,pathrock@protonmail.com,laconic1qrss36gx7rx58uffn60lx99fr0d929566mpafj,9.831866355308070,,,,,,, -,,Pablo Alexandro Lema Diez de Medina,pablo@nodesoda.com,laconic1g3dugtdlardfg28teljfzftzfeynjheae07ytr,8.265493084246450,,,,,,, -,,Azmy Rachman K,orang3club@gmail.com,laconic1rcssfrp47s0xmg2vahshmf6zcaadqamjel2a7r,6.072570504760190,,,,,,, -,,CHUKWUDALU EMMANUEL IFEDIORA,chukwudaluemmanuel7@gmail.com,laconic1jeylpuu59d4a5qynj8xm99ssgmk7w5w95n6q00,4.153763247709720,,,,,,, -,,VICTOR SOMTOCHUKWU OKOLI,foroncecomeandseeme@gmail.com,laconic17njvfpqxv6nc6ky5yvkk5g2r35tlvkqk4x0as9,4.153763247709720,,,,,,, -,,CHINEDU ANTHONY AGUDE,dalupython@gmail.com,laconic1hw5vr47nl4876nd728vcy4m44j57un67guldlv,4.153763247709720,,,,,,, -,,ABUCHI COLUMBUS NDIBE,dyingifeellike@gmail.com,laconic1nthmxgdtf58mntuukz4r5v0ry6zctl2ve9aqpe,4.153763247709720,,,,,,, -,,WISDOM CHUKWUBUIKEM NWAUBANI,chimdioligarchy@gmail.com,laconic17zcxj4fyaef42da7pk0ccqxz2a8fns5fxs2qlr,4.153763247709720,,,,,,, -,,Azeez Adebowale Adekanbi,kentmererashida@gmail.com,laconic1l7tc37faxf9knl9rxmkfzc26dchnrtzvderurf,4.153763247709720,,,,,,, -,,Ikenna Ozigbo,shareladyboss@gmail.com,laconic1aahpp8vknsq72vamrfgnn86m4ple5xqnd5dydz,4.153763247709720,,,,,,, -,,VICTOR EZECHUKWU NZENWA,pushinmoni@gmail.com,laconic12wrfzczt0qgknjv9nle4uczujpqxrkj7p4v9uj,4.153763247709720,,,,,,, -,,IFEANYI EMMANUEL EJIM,eejim399@gmail.com,laconic1z3syuquq0gdhvhtjs75lcsrpplm79ycxjtdge6,3.957966588827020,,,,,,, -,,Charles Ekeigbo,preciousuwem83@gmail.com,laconic122mal2jwd9x2vfxrpxtd9vdz85ksggeq0tlle5,3.957966588827020,,,,,,, -,,CHIMEZIE CHRISTOPHER IFEDIORA,ethskytrixsmartcontract@gmail.com,laconic15y76s0ml2dfzef3y07x6hmcngtcaw59d8y2sls,3.605532602838150,,,,,,, -,,TARAS GRUZHEVSKIY,office@noders.team,laconic1yavpc0fjk3ze33kfuuc5fra5x3nzs20ajhpef5,3.292257948625830,,,,,,, -,,Olusola Adebesin,olusolaadebesin0@gmail.com,laconic1qzwl52vns3gecngsh59y5yvg9a8m345dz2qv8x,3.292257948625830,,,,,,, -,,ENIOLA OLUWAFEMI OLATUNDE,olatenny@gmail.com,laconic1nr6z78gkf6swk9m02qtdazde7jr9csetv402wr,2.783186635530810,,,,,,, -,,DANIEL OLUMIDE OLATUNDE,reabumble@gmail.com,laconic17uukytqarpu6wsmjcqgfcs2tjhwhfu6eq72cpw,2.783186635530810,,,,,,, -,,OLUWASEUN JOSEPH-AYOTUNDE OLATUNDE,ecares4mee@gmail.com,laconic17g9ytaauphqv5lawthk2hj9n04eardz28yvnfk,2.783186635530810,,,,,,, -,,Temiloluwa Olasiwale,enny4wise@gmail.com,laconic16pxr8lupfcswatynedc76ynw5f74jpcmjt28vs,2.783186635530810,,,,,,, -,,David Akinyemi,f333miola@gmail.com,laconic1xnvd8fdr5zwfa2thdlr2pg22ndg4e0dptqfav9,2.783186635530810,,,,,,, -,,JUWON SIMON OLATUNDE,enny4bea@gmail.com,laconic1qykx88yyy3a6udmqfu3aej40rymklnynfr5cq8,2.783186635530810,,,,,,, -,,JULIET CHINECHEREM OKEIFUFE,richardjuliet1996@gmail.com,laconic1qjjvdwlt2u5cgmaxn6l66nwnqw9fs4vl7g045h,2.783186635530810,,,,,,, -,,OLUWATOBI DANIEL OLAYANJU,barthenry41@gmail.com,laconic1mdzgqw7re2fuws0uycpm90nt07d6ntsk5alt4j,2.783186635530810,,,,,,, -,,IFEOLUWA JOSEPH ADELABU,danieelleexx@gmail.com,laconic157jy998f0x2m0kms8r6mmfs3zazljpd0svd9ne,2.783186635530810,,,,,,, -,,EMEKA OBI,kobi6542@gmail.com,laconic1rdtz32xsgw7yrjfrue36pglevpymc5aflu4cfy,2.783186635530810,,,,,,, -,,Vladimir Skopintsev,posthuman.validator@gmail.com,laconic14dzwrzdfgln6z2vuu0jncvwjt2l7e4yl7slmjq,2.646128974312920,,,,,,, -,,,,,,,,,,,, -,,,,Total testnet allocation,3096.104787518470000,,,,,,, \ No newline at end of file diff --git a/data/distribution.json b/data/distribution.json deleted file mode 100644 index aa4ed23..0000000 --- a/data/distribution.json +++ /dev/null @@ -1,404 +0,0 @@ -{ - "Seed Investor 1": { - "total_lps_allocation": 6480.0, - "lock_months": 12.0, - "vest_months": null, - "laconic_address": "foundation1" - }, - "Seed Investor 2": { - "total_lps_allocation": 6480.0, - "lock_months": 12.0, - "vest_months": null, - "laconic_address": "foundation1" - }, - "Seed Investor 3": { - "total_lps_allocation": 6480.0, - "lock_months": 12.0, - "vest_months": null, - "laconic_address": "foundation1" - }, - "Seed Investor 4": { - "total_lps_allocation": 1361.0, - "lock_months": 6.0, - "vest_months": null, - "laconic_address": "foundation1" - }, - "Team": { - "total_lps_allocation": 25920.0, - "lock_months": null, - "vest_months": 36.0, - "laconic_address": "ltd1" - }, - "For sale": { - "total_lps_allocation": null, - "lock_months": null, - "vest_months": null, - "laconic_address": "foundation2" - }, - "Community Module": { - "total_lps_allocation": 38880.0, - "lock_months": null, - "vest_months": null, - "laconic_address": "autogenerated" - }, - "Autonomous": { - "total_lps_allocation": null, - "lock_months": null, - "vest_months": null, - "laconic_address": "TBD" - }, - "Mito": { - "total_lps_allocation": null, - "lock_months": null, - "vest_months": null, - "laconic_address": "TBD" - }, - "Owen": { - "total_lps_allocation": null, - "lock_months": null, - "vest_months": null, - "laconic_address": "TBD" - }, - "Mark": { - "total_lps_allocation": null, - "lock_months": null, - "vest_months": null, - "laconic_address": "TBD" - }, - "Zee": { - "total_lps_allocation": null, - "lock_months": null, - "vest_months": null, - "laconic_address": "TBD" - }, - "Remainder (marketing)": { - "total_lps_allocation": 9863.89521248153, - "lock_months": null, - "vest_months": null, - "laconic_address": "foundation3" - }, - "BlackBlocks": { - "total_lps_allocation": 437.568163257075, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic128vt4we3s044zycwydz9f6amzrlp7r6lnputdg" - }, - "rxpwnz": { - "total_lps_allocation": 366.236759056674, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic19h70dln5ktxpc8mcam5nm22glr7h9qtlzvvrtq" - }, - "MekongLabs": { - "total_lps_allocation": 347.478327502243, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic195s2w429xuxqagkz54n55dcpfz4nwl0k62qnet" - }, - "Silent": { - "total_lps_allocation": 143.558393240641, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1256aqyag45x84usd6xj053musfcql74j4j3ll3" - }, - "Barg Systems": { - "total_lps_allocation": 152.988072312237, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1mjzrgc8ucspjz98g76c8pce026l5newrujetx0" - }, - "Dream Gallery": { - "total_lps_allocation": 117.107359272441, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1f9j8n9rqsekzp0rffe3298pytms4hfz20khge3" - }, - "Ellipfra": { - "total_lps_allocation": 114.304453473952, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1axg567nvu92un33z6z547n7klkeq6ud37pwz35" - }, - "High Stakes": { - "total_lps_allocation": 83.6163176414838, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1vy8tnar3w7zxusnwhp5jdzw97rusr2d6n8ch5c" - }, - "Cosmos Spaces": { - "total_lps_allocation": 21.0973594395545, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1qsvrehuchjquanwm7gsx7cvze8t959l7zf0zpw" - }, - "Hypha": { - "total_lps_allocation": 161.45, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1s03twj8fedmcn04kzt2z35mwy34e7hxnm423sh" - }, - "KenZ": { - "total_lps_allocation": 103.440578336577, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic16v0lazxvmccs0893g58fqa65m6344dlcpxrvs0" - }, - "spidey": { - "total_lps_allocation": 101.548280416612, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1a2h0eck0dra2fu9xcama9rrygncjc30ex35ly5" - }, - "Wavefive": { - "total_lps_allocation": 93.2797612445932, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1dx3jyjfpcwdwufj5uuufk84f5ugm5h4wf3jsl2" - }, - "DragonZ": { - "total_lps_allocation": 84.1679353908511, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1f7tursd29yrk3mnys3javqngraj5ls7k5h3vvv" - }, - "yandc": { - "total_lps_allocation": 81.1032354987346, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic14vzrlac5zte5nju9fm0ktzfz7e4zss74f6lpzx" - }, - "CalvinJoe": { - "total_lps_allocation": 76.6810175336002, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1nmuxuz3z2xj5fqf2sz5nn0u2r2al7mutsl8pm7" - }, - "Nodeify": { - "total_lps_allocation": 75.4880471057965, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic18uc9h349nd0w62vnleu8ywu3sur7ly0kdsgmg3" - }, - "Twaltoner": { - "total_lps_allocation": 74.8709934362428, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1360txwdlk4z0604vd22dcarxt9w3ddj8d8mz8m" - }, - "AndreasV": { - "total_lps_allocation": 74.6344561962473, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1wrwl5557yxgqkwq4djlrz33x5nd5f0j9vh42jg" - }, - "Elf": { - "total_lps_allocation": 73.1946643006221, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1ka6xtcejersljsmslc6tw9uxvfmans476v98r0" - }, - "twelly8": { - "total_lps_allocation": 73.1226747058408, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1ljwtpta6xfgtnk0e03h4t77chjygv399pr6utz" - }, - "Quitlantarah": { - "total_lps_allocation": 73.0404008832337, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1vfs90x57ufs87tn9h6zs3xylnzh97f03qy0ggz" - }, - "laconic1qw26grwct7xtjdrlseurh9v6g8wu2x3vded63g": { - "total_lps_allocation": 15.7449254535657, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1qw26grwct7xtjdrlseurh9v6g8wu2x3vded63g" - }, - "laconic1r70vhqwvf7dw2twy6m77f34fzeshp9fqxtxace": { - "total_lps_allocation": 11.5940362852524, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1r70vhqwvf7dw2twy6m77f34fzeshp9fqxtxace" - }, - "laconic1nezjpcfflf8nc5yt2hx5yd20ry6ka066tth38w": { - "total_lps_allocation": 11.5940362852524, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1nezjpcfflf8nc5yt2hx5yd20ry6ka066tth38w" - }, - "laconic1xwwy9944lgu3djvgmk4l4x59x5cjzczcxuj9f5": { - "total_lps_allocation": 11.3786599604814, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1xwwy9944lgu3djvgmk4l4x59x5cjzczcxuj9f5" - }, - "laconic1kkv020aj5z8es9shrylvlcjfextm2srg0085ml": { - "total_lps_allocation": 9.83186635530807, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1kkv020aj5z8es9shrylvlcjfextm2srg0085ml" - }, - "laconic1qrss36gx7rx58uffn60lx99fr0d929566mpafj": { - "total_lps_allocation": 9.83186635530807, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1qrss36gx7rx58uffn60lx99fr0d929566mpafj" - }, - "laconic1g3dugtdlardfg28teljfzftzfeynjheae07ytr": { - "total_lps_allocation": 8.26549308424645, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1g3dugtdlardfg28teljfzftzfeynjheae07ytr" - }, - "laconic1rcssfrp47s0xmg2vahshmf6zcaadqamjel2a7r": { - "total_lps_allocation": 6.07257050476019, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1rcssfrp47s0xmg2vahshmf6zcaadqamjel2a7r" - }, - "laconic1jeylpuu59d4a5qynj8xm99ssgmk7w5w95n6q00": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1jeylpuu59d4a5qynj8xm99ssgmk7w5w95n6q00" - }, - "laconic17njvfpqxv6nc6ky5yvkk5g2r35tlvkqk4x0as9": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic17njvfpqxv6nc6ky5yvkk5g2r35tlvkqk4x0as9" - }, - "laconic1hw5vr47nl4876nd728vcy4m44j57un67guldlv": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1hw5vr47nl4876nd728vcy4m44j57un67guldlv" - }, - "laconic1nthmxgdtf58mntuukz4r5v0ry6zctl2ve9aqpe": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1nthmxgdtf58mntuukz4r5v0ry6zctl2ve9aqpe" - }, - "laconic17zcxj4fyaef42da7pk0ccqxz2a8fns5fxs2qlr": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic17zcxj4fyaef42da7pk0ccqxz2a8fns5fxs2qlr" - }, - "laconic1l7tc37faxf9knl9rxmkfzc26dchnrtzvderurf": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1l7tc37faxf9knl9rxmkfzc26dchnrtzvderurf" - }, - "laconic1aahpp8vknsq72vamrfgnn86m4ple5xqnd5dydz": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1aahpp8vknsq72vamrfgnn86m4ple5xqnd5dydz" - }, - "laconic12wrfzczt0qgknjv9nle4uczujpqxrkj7p4v9uj": { - "total_lps_allocation": 4.15376324770972, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic12wrfzczt0qgknjv9nle4uczujpqxrkj7p4v9uj" - }, - "laconic1z3syuquq0gdhvhtjs75lcsrpplm79ycxjtdge6": { - "total_lps_allocation": 3.95796658882702, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1z3syuquq0gdhvhtjs75lcsrpplm79ycxjtdge6" - }, - "laconic122mal2jwd9x2vfxrpxtd9vdz85ksggeq0tlle5": { - "total_lps_allocation": 3.95796658882702, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic122mal2jwd9x2vfxrpxtd9vdz85ksggeq0tlle5" - }, - "laconic15y76s0ml2dfzef3y07x6hmcngtcaw59d8y2sls": { - "total_lps_allocation": 3.60553260283815, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic15y76s0ml2dfzef3y07x6hmcngtcaw59d8y2sls" - }, - "laconic1yavpc0fjk3ze33kfuuc5fra5x3nzs20ajhpef5": { - "total_lps_allocation": 3.29225794862583, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1yavpc0fjk3ze33kfuuc5fra5x3nzs20ajhpef5" - }, - "laconic1qzwl52vns3gecngsh59y5yvg9a8m345dz2qv8x": { - "total_lps_allocation": 3.29225794862583, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1qzwl52vns3gecngsh59y5yvg9a8m345dz2qv8x" - }, - "laconic1nr6z78gkf6swk9m02qtdazde7jr9csetv402wr": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1nr6z78gkf6swk9m02qtdazde7jr9csetv402wr" - }, - "laconic17uukytqarpu6wsmjcqgfcs2tjhwhfu6eq72cpw": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic17uukytqarpu6wsmjcqgfcs2tjhwhfu6eq72cpw" - }, - "laconic17g9ytaauphqv5lawthk2hj9n04eardz28yvnfk": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic17g9ytaauphqv5lawthk2hj9n04eardz28yvnfk" - }, - "laconic16pxr8lupfcswatynedc76ynw5f74jpcmjt28vs": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic16pxr8lupfcswatynedc76ynw5f74jpcmjt28vs" - }, - "laconic1xnvd8fdr5zwfa2thdlr2pg22ndg4e0dptqfav9": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1xnvd8fdr5zwfa2thdlr2pg22ndg4e0dptqfav9" - }, - "laconic1qykx88yyy3a6udmqfu3aej40rymklnynfr5cq8": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1qykx88yyy3a6udmqfu3aej40rymklnynfr5cq8" - }, - "laconic1qjjvdwlt2u5cgmaxn6l66nwnqw9fs4vl7g045h": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1qjjvdwlt2u5cgmaxn6l66nwnqw9fs4vl7g045h" - }, - "laconic1mdzgqw7re2fuws0uycpm90nt07d6ntsk5alt4j": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1mdzgqw7re2fuws0uycpm90nt07d6ntsk5alt4j" - }, - "laconic157jy998f0x2m0kms8r6mmfs3zazljpd0svd9ne": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic157jy998f0x2m0kms8r6mmfs3zazljpd0svd9ne" - }, - "laconic1rdtz32xsgw7yrjfrue36pglevpymc5aflu4cfy": { - "total_lps_allocation": 2.78318663553081, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic1rdtz32xsgw7yrjfrue36pglevpymc5aflu4cfy" - }, - "laconic14dzwrzdfgln6z2vuu0jncvwjt2l7e4yl7slmjq": { - "total_lps_allocation": 2.64612897431292, - "lock_months": null, - "vest_months": null, - "laconic_address": "laconic14dzwrzdfgln6z2vuu0jncvwjt2l7e4yl7slmjq" - } -} \ No newline at end of file diff --git a/docs/run-first-validator.md b/docs/run-first-validator.md index 241ab6b..8d712ad 100644 --- a/docs/run-first-validator.md +++ b/docs/run-first-validator.md @@ -4,7 +4,7 @@ - [ansible](playbooks/README.md#ansible-installation) - [laconic-so](https://github.com/cerc-io/stack-orchestrator/?tab=readme-ov-file#install) -- LPS distribution spreadsheet URL or excel file path +- LPS distribution spreadsheet URL or csv file path ## Export testnet state @@ -49,16 +49,10 @@ - Generate LPS lockup distribution JSON file ```bash - # -i, --input: Google Sheet URL or local Excel file path (required) - # -d, --dir: Destination folder for the generated distribution.json file (optional, defaults to current directory) - # -s, --sheet: Sheet name to read (optional, defaults to "Genesis Allocation") - ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh \ - -i "" \ - -d "" \ - -s "" + ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh -i "" -d "" ``` - - This will generate the `distribution.json` file at `~/cerc/laconicd-stack/distribution.json` + - This will generate the `distribution.json` file - Copy over the LPS lockup distribution `distribution.json` file to target machine diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py index fc4cfbe..616896c 100644 --- a/scripts/generate-lps-distribution-json.py +++ b/scripts/generate-lps-distribution-json.py @@ -55,12 +55,17 @@ def convert_csv_to_json(csv_path, json_path): result = {} for _, row in df.iterrows(): placeholder = str(row['Placeholder']) if not pd.isna(row['Placeholder']) else '' + laconic_address = str(row['Laconic Address']) if not pd.isna(row['Laconic Address']) else '' + + # Use laconic_address as key if placeholder is missing or empty key = placeholder if placeholder and placeholder.lower() != 'nan' else laconic_address + # Skip the row if both 'Placeholder' and 'Laconic Address' are missing or invalid if not key or key.lower() == 'nan': continue + # If key is the laconic address, validate that it's a valid bech32 address if key == laconic_address: hrp, data = bech32_decode(laconic_address) if hrp is None or data is None or not hrp.startswith("laconic"): @@ -91,7 +96,6 @@ def main(): parser = argparse.ArgumentParser(description='Generate LPS distribution JSON from CSV or Google Sheet') parser.add_argument('--input', '-i', required=True, help='Input: Google Sheet URL or local CSV file path') parser.add_argument('--output', '-o', default='distribution.json', help='Output JSON file path (default: distribution.json)') - parser.add_argument('--sheet', '-s', default='Genesis Allocation', help='Sheet name to read (default: Genesis Allocation)') args = parser.parse_args() diff --git a/scripts/generate-lps-lock.sh b/scripts/generate-lps-lock.sh index fc3c7a3..b43f123 100755 --- a/scripts/generate-lps-lock.sh +++ b/scripts/generate-lps-lock.sh @@ -5,7 +5,6 @@ set -e # Default values INPUT="" OUTPUT_DIR="." -SHEET="Genesis Allocation" # Parse command line arguments while [[ $# -gt 0 ]]; do @@ -18,13 +17,9 @@ while [[ $# -gt 0 ]]; do OUTPUT_DIR="$2" shift 2 ;; - -s|--sheet) - SHEET="$2" - shift 2 - ;; *) echo "Unknown option: $1" - echo "Usage: $0 -i|--input [-d|--dir ] [-s|--sheet ]" + echo "Usage: $0 -i|--input [-d|--dir ]" exit 1 ;; esac @@ -33,7 +28,7 @@ done # Check if input is provided if [ -z "$INPUT" ]; then echo "Error: Input URL or path is required" - echo "Usage: $0 -i|--input [-d|--dir ] [-s|--sheet ]" + echo "Usage: $0 -i|--input [-d|--dir ]" exit 1 fi @@ -55,8 +50,7 @@ fi echo "Running LPS lock generation script..." "$venv_dir/bin/python" "$script_dir/generate-lps-distribution-json.py" \ --input "$INPUT" \ - --output "$OUTPUT_DIR/distribution.json" \ - --sheet "$SHEET" + --output "$OUTPUT_DIR/distribution.json" # Clean up venv echo "Cleaning up..." -- 2.45.2 From 96ce72e6eada1fce7b480d056caa87e399c679a2 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 3 Jun 2025 18:20:29 +0530 Subject: [PATCH 10/11] Update README steps for demo --- docs/demo.md | 14 +++++++++++--- docs/run-first-validator.md | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/demo.md b/docs/demo.md index 6a04efd..40270f7 100644 --- a/docs/demo.md +++ b/docs/demo.md @@ -10,11 +10,11 @@ cargo install tmkms --features=softsign --version=0.14.0 ``` - testnet-state.json ([exported testnet state](./run-first-validator.md#export-testnet-state)) -- distribution.json (JSON containing the `lps_lockup` distribution) +- LPS distribution spreadsheet URL or CSV file path ## Steps -- In current working directory demo, keep exported `testnet-state.json` and `distribution.json` file from prerequisites +- In current working directory demo, keep exported `testnet-state.json` file from prerequisites - Fetch stack: @@ -22,6 +22,14 @@ laconic-so fetch-stack git.vdb.to/cerc-io/laconicd-stack --git-ssh --pull ``` +- Generate LPS lockup distribution JSON file + + ```bash + ~/cerc/laconicd-stack/scripts/generate-lps-lock.sh -i "" -d "~/cerc/laconicd-stack/data" + ``` + + - This will generate the `distribution.json` file + - Export current working directory ```bash @@ -32,7 +40,7 @@ ```bash export EXPORTED_STATE_PATH=$CWD/testnet-state.json - export LPS_DISTRIBUTION_PATH=$CWD/distribution.json + export LPS_DISTRIBUTION_PATH=~/cerc/laconicd-stack/data/distribution.json # Test address that does not exist on testnet chain export EARLY_SUPPORTS_ACC_ADDR=laconic1gwytamfk3m5n0gsawh5vpwxkwd3vapmvzpp6nz diff --git a/docs/run-first-validator.md b/docs/run-first-validator.md index 8d712ad..1037f56 100644 --- a/docs/run-first-validator.md +++ b/docs/run-first-validator.md @@ -4,7 +4,7 @@ - [ansible](playbooks/README.md#ansible-installation) - [laconic-so](https://github.com/cerc-io/stack-orchestrator/?tab=readme-ov-file#install) -- LPS distribution spreadsheet URL or csv file path +- LPS distribution spreadsheet URL or CSV file path ## Export testnet state -- 2.45.2 From cb3e8c14d3812b70d49e8a131e8b9c47d82f7aa1 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Wed, 4 Jun 2025 15:58:39 +0530 Subject: [PATCH 11/11] Use constants for column names --- docs/demo.md | 2 +- docs/run-first-validator.md | 2 +- scripts/generate-lps-distribution-json.py | 58 ++++++++++++++--------- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/docs/demo.md b/docs/demo.md index 40270f7..251a7d5 100644 --- a/docs/demo.md +++ b/docs/demo.md @@ -10,7 +10,7 @@ cargo install tmkms --features=softsign --version=0.14.0 ``` - testnet-state.json ([exported testnet state](./run-first-validator.md#export-testnet-state)) -- LPS distribution spreadsheet URL or CSV file path +- LPS distribution Google spreadsheet URL or CSV file path ## Steps diff --git a/docs/run-first-validator.md b/docs/run-first-validator.md index 1037f56..a3bc9b6 100644 --- a/docs/run-first-validator.md +++ b/docs/run-first-validator.md @@ -4,7 +4,7 @@ - [ansible](playbooks/README.md#ansible-installation) - [laconic-so](https://github.com/cerc-io/stack-orchestrator/?tab=readme-ov-file#install) -- LPS distribution spreadsheet URL or CSV file path +- LPS distribution Google spreadsheet URL or CSV file path ## Export testnet state diff --git a/scripts/generate-lps-distribution-json.py b/scripts/generate-lps-distribution-json.py index 616896c..d22aa42 100644 --- a/scripts/generate-lps-distribution-json.py +++ b/scripts/generate-lps-distribution-json.py @@ -7,6 +7,34 @@ import argparse import urllib.parse from bech32 import bech32_decode +# Column names in the input CSV +PLACEHOLDER_COLUMN = 'Placeholder' +LACONIC_ADDRESS_COLUMN = 'Laconic Address' +TOTAL_LPS_ALLOCATION_COLUMN = 'Total LPS Allocation' +LOCK_MONTHS_COLUMN = 'Lock (months)' +VEST_MONTHS_COLUMN = 'Vest (months)' + +# Required columns in the input CSV +REQUIRED_COLUMNS = [ + PLACEHOLDER_COLUMN, + LACONIC_ADDRESS_COLUMN, + TOTAL_LPS_ALLOCATION_COLUMN, + LOCK_MONTHS_COLUMN, + VEST_MONTHS_COLUMN +] + +def to_number(val): + """ + Convert a value to a number, handling empty values and invalid inputs. + Returns None for empty or invalid values. + """ + if pd.isna(val) or str(val).strip() == '': + return None + try: + return float(val) + except (ValueError, TypeError): + return None + def get_csv_download_url(google_sheet_url): """ Convert a full Google Sheets URL to a CSV export URL using the `gid` in the query string. @@ -41,22 +69,14 @@ def convert_csv_to_json(csv_path, json_path): Read the CSV file, extract columns, and save as JSON. """ df = pd.read_csv(csv_path) - required_columns = [ - 'Placeholder', - 'Laconic Address', - 'Total LPS Allocation', - 'Lock (months)', - 'Vest (months)' - ] - for col in required_columns: + for col in REQUIRED_COLUMNS: if col not in df.columns: raise Exception(f'Missing required column: {col}') result = {} for _, row in df.iterrows(): - placeholder = str(row['Placeholder']) if not pd.isna(row['Placeholder']) else '' - - laconic_address = str(row['Laconic Address']) if not pd.isna(row['Laconic Address']) else '' + placeholder = str(row[PLACEHOLDER_COLUMN]) if not pd.isna(row[PLACEHOLDER_COLUMN]) else '' + laconic_address = str(row[LACONIC_ADDRESS_COLUMN]) if not pd.isna(row[LACONIC_ADDRESS_COLUMN]) else '' # Use laconic_address as key if placeholder is missing or empty key = placeholder if placeholder and placeholder.lower() != 'nan' else laconic_address @@ -72,19 +92,11 @@ def convert_csv_to_json(csv_path, json_path): print(f"Skipping invalid Laconic address: {laconic_address}") continue - def to_number(val): - if pd.isna(val) or str(val).strip() == '': - return None - try: - return float(val) - except (ValueError, TypeError): - return None - entry = { - 'total_lps_allocation': to_number(row['Total LPS Allocation']), - 'lock_months': row['Lock (months)'] if not pd.isna(row['Lock (months)']) else None, - 'vest_months': row['Vest (months)'] if not pd.isna(row['Vest (months)']) else None, - 'laconic_address': row['Laconic Address'] if not pd.isna(row['Laconic Address']) else None + 'total_lps_allocation': to_number(row[TOTAL_LPS_ALLOCATION_COLUMN]), + 'lock_months': row[LOCK_MONTHS_COLUMN] if not pd.isna(row[LOCK_MONTHS_COLUMN]) else None, + 'vest_months': row[VEST_MONTHS_COLUMN] if not pd.isna(row[VEST_MONTHS_COLUMN]) else None, + 'laconic_address': row[LACONIC_ADDRESS_COLUMN] if not pd.isna(row[LACONIC_ADDRESS_COLUMN]) else None } result[key] = entry -- 2.45.2