What?
Formance Stack เป็น open-source tool ที่ออกแบบมาเพื่อที่จะช่วย developer สร้าง, จัดการ, และติดตามการเข้าออกของเงินในบัญชี โดยเราสามารถนำ tool นี้มีใช้ได้ในโปรเจ็คขนาดเล็ก หรือแม้กระทั่งใน platform ทางการเงินขนาดใหญ่
Formance Ledger?
Formance Ledger คือ service ที่ทำให้เราสามารถติดตามการเคลื่อนไหวหรือ สถานะเกี่ยวกับการเงินได้แบบ real-time และเราสามารถ disign และบันทึก transaction ทางการเงินที่มีความสับซ้อนได้อีกด้วย ซึ่งเราสามารถเขียนโปรแกรมสั่งการได้โดยใช้ Numscript ที่ทำหน้าที่เป็น DSL (domain-specific language) ที่ถูกออกแบบมาช่วยเรา model transaction ทางการเงิน
Hello Formance!!!
มาลองใช้ง่ายแบบง่ายๆเพื่อให้เห็นภาพมากขึ้น Formance ได้จัดเตรียมวิธี install service ไว้หลายวิธีแต่วิธีที่ผมเลือกจะใช้ Docker
docker run -p 3068:3068 \
-v $HOME/numary:/root/.numary \
--env NUMARY_SERVER_HTTP_BIND_ADDRESS="0.0.0.0:3068" \
ghcr.io/formancehq/ledger:latest
หรือ Docker compose ซึ่งจะมาพร้อมกับ service postgres ซึ่งเป็น database ที่ใช้แทน default ที่เป็น sqlite
curl -L https://raw.githubusercontent.com/formancehq/ledger/main/docker-compose.yml -o docker-compose.yml
docker-compose up -d
ทดสอบโดยการใช้คำสั่ง
curl -X GET http://127.0.0.1:3068/_info
Hello world!!!
ในหัวนี้เราจะเรียนรู้:
- การสร้าง Formance Ledger
- สร้าง models transaction และ account โดยใช้ Numscript
- นำเงินเข้าสู่ระบบด้วย @world account
- ตรวจสอบ transaction และ ยอดคงเหลือใน account
อธิบาย @world account เพิ่มเติมที่ต้องมี account นี้เนื่องจากตัว Formance ledger มีการกำหนดว่าเงินที่เข้ามาในระบบไม่สามารถเสกมาจากอากาศลอยๆได้ ดังนั้นจึงต้องมี @world account เพื่อใช้นำเงินจากภายนอกเข้ามาสู่ในระบบ ledger ของเรา
จากหัวข้อด้านบนตอนนี้เราจะมี service Ledger รันอยู่ในเครื่องแล้ว เราลองมาสร้าง transaction แรกกันด้วยการสร้าง Numscript
first.num
send [COIN 100] (
source = @world
destination = @centralbank
)
jq -Rs '{plain: .}' first.num \
| curl -H "Content-Type: application/json" \
-X POST --data-binary @- \
https://localhost/api/ledger/{default}/script
Checking balances
ตรวจสอบรายการสามารถทำได้ด้วยการส่งคำสั่ง
curl --location --request GET 'http://localhost/api/ledger/{quickstart}/aggregate/balances?address=centralbank'
Storage consideration
ตัว Formance เองรองรับการเก็บข้อมูลไว้ใน storage 2 อย่างคือ Sqlite และ Postgres ซึ่งโดย default แล้วตัวระบบจะเลือกใช้ Sqlite มาให้ซึ่งสะดวกและง่ายสำหรับการทำการทดสอบบน local แต่ทางระบบเองก็มีการเตือนว่าไม่เหมาะสำหรับการนำมาใช้บน production product และกำลังจะถูก deprecated ใน Formance version 2.X
ตัวเลือกเดียวที่เหมาะสมก็จะเหลือแค่ Postgres ซึ่งเราสามารถใช้งานได้ด้วยการคำหนดค่า Environment
NUMARY_STORAGE_DRIVER=postgres \
NUMARY_STORAGE_POSTGRES_CONN_STRING=postgresql://localhost/dbname \
Concurrency Model
Formance มีการออกแบบการควบคุม concurrency ของ transaction เพื่อป้องกันการเกิด race condition เป็น 2 ส่วนคือ
- Pre-commit in-memory or Redis-based locking
- Optimistic locking
ส่วนการเลือกระหว่าง in-memory or Redis นั่นพิจารณาจากว่าหากเรา deploy แบบ multi-instances ให้เลือกใช้ Redis
อ่านเพิ่มเติม
Ledger separation
การเลือกแบ่ง Ledger ใน Formance หรือพูดง่ายๆว่าการแบ่ง schema ของ postgres ว่าเราควรจะทำเป็น single ledger หรือ multi-ledger นั่นมีหลักการตัดสิน 2 ข้อคือ
- หาก application ของเราไม่มีความจำเป็นต้องแชร์ข้อมูลข้าม ledger กันสามารถทำ multi-ledger ได้
- application ที่มี workload ด้าน write สูงและสามารถเก็บข้อมูลแยกกันได้สามารถพิจารณาทำ multi-ledger ได้
Account
เป็นเสมือน container สำหรับ assets เราสามารถส่งและรับ assets ได้ผ่าน transaction โดยผลรวมของ account จะเท่ากับ
balance(account)=∑postings(destination)−∑postings(source)
การตั้งชื่อ account มีการกำหนดว่าต้องตาม เงื่อนไขดังนี้
^[a-zA-Z_0-9]+(:[a-zA-Z_0-9]+){0,}$
และแนะนำให้ใช้เครื่องหมาย colon ให้การแบ่ง structure เช่น
payments:001:authorizations:001
sales:001:contract
นอกจากนั้นใน account เรายังสามารถเพิ่มตัว metadata เข้าไปได้ด้วยเพื่อใช้อธิบายรายละเอียดเพิ่มเติมของ account นั่นๆ
เพิ่มเติม
Posting
คือการเคลื่อนที่ของจำนวนของ asset จาก account นึงไปยังอีก account นึง เช่น Alice ให้ 100 coins ไปที่ Bob
{
"source": "alice",
"destination": "bob",
"asset": "COIN",
"amount": 100
}
Transaction
ใน Formance transaction คือการ model การรวมกันของ posting ซึ่งเจตนาคือต้องการต้องการทำให้เป็น atomically ตัวอย่างเช่น Alice ใช้ coin ซื้อ gem ผ่าน counter
{
"postings": [
{
"source": "alice",
"destination": "teller",
"amount": 100,
"asset": "COIN"
},
{
"source": "teller",
"destination": "alice",
"amount": 5,
"asset": "GEM"
}
]
}
Architecture
architecture
Control dashborad
control dashborad
https://control.formance.com/
Mastering Numscript
coming soon
numscript template
Top comments (0)