Skip to content
This repository was archived by the owner on Feb 8, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 13 additions & 54 deletions storage/postgres/migrations/plugin/20250630152230_fee_runs.sql
Original file line number Diff line number Diff line change
@@ -1,42 +1,19 @@
-- +goose Up
-- +goose StatementBegin
-- Create fee_run table
CREATE TABLE IF NOT EXISTS fee_run (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'sent', 'completed', 'failed')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
tx_hash VARCHAR(66),
policy_id UUID NOT NULL REFERENCES plugin_policies(id) ON DELETE CASCADE
);

-- Create fee table
CREATE TABLE IF NOT EXISTS fee (
id UUID PRIMARY KEY,
fee_run_id UUID NOT NULL REFERENCES fee_run(id) ON DELETE CASCADE,
amount INTEGER NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TYPE fee_batch_status as ENUM ('draft', 'sent', 'completed', 'failed');

-- Create view for fee runs with total amounts
CREATE OR REPLACE VIEW fee_run_with_totals AS
SELECT
fr.id,
fr.status,
fr.created_at,
fr.updated_at,
fr.tx_hash,
fr.policy_id,
COALESCE(SUM(fi.amount), 0) as total_amount,
COUNT(fi.id) as fee_count
FROM fee_run fr
LEFT JOIN fee fi ON fr.id = fi.fee_run_id
GROUP BY fr.id, fr.status, fr.created_at, fr.updated_at, fr.tx_hash, fr.policy_id;

-- Create indexes for better performance
CREATE INDEX IF NOT EXISTS idx_fee_run_status ON fee_run(status);
CREATE INDEX IF NOT EXISTS idx_fee_run_created_at ON fee_run(created_at);
CREATE INDEX IF NOT EXISTS idx_fee_id_fee_run_id ON fee(fee_run_id);
CREATE TABLE IF NOT EXISTS fee_batch (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
batch_id UUID NOT NULL, -- this is the id of the batch credit "fee" on the verifier
public_key VARCHAR(66) NOT NULL,
status fee_batch_status NOT NULL DEFAULT 'draft',
amount BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
Comment on lines +13 to +14
Copy link

Copilot AI Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timestamp columns use different data types than the schema.sql file. Here created_at uses TIMESTAMP while in schema.sql it uses timestamp with time zone. This inconsistency could lead to timezone-related issues.

Suggested change
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +14
Copy link

Copilot AI Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timestamp columns use different data types than the schema.sql file. Here updated_at uses TIMESTAMP while in schema.sql it uses timestamp with time zone. This inconsistency could lead to timezone-related issues.

Suggested change
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),

Copilot uses AI. Check for mistakes.
tx_hash VARCHAR(66)
);

-- Create trigger to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at_column()
Expand All @@ -47,29 +24,11 @@ BEGIN
END;
$$ language 'plpgsql';

CREATE TRIGGER update_fee_run_updated_at
BEFORE UPDATE ON fee_run
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
-- Drop trigger first
DROP TRIGGER IF EXISTS update_fee_run_updated_at ON fee_run;

-- Drop function
DROP FUNCTION IF EXISTS update_updated_at_column();
Copy link

Copilot AI Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The migration drops the update_updated_at_column() function in the Down section, but this function may be used by other tables or triggers in the database. Dropping it could break other functionality that depends on this shared function.

Suggested change
DROP FUNCTION IF EXISTS update_updated_at_column();

Copilot uses AI. Check for mistakes.

-- Drop indexes
DROP INDEX IF EXISTS idx_fee_id_fee_run_id;
DROP INDEX IF EXISTS idx_fee_run_created_at;
DROP INDEX IF EXISTS idx_fee_run_status;

-- Drop view
DROP VIEW IF EXISTS fee_run_with_totals;

-- Drop tables (in reverse order due to foreign key constraints)
DROP TABLE IF EXISTS fee;
DROP TABLE IF EXISTS fee_run;
DROP TABLE IF EXISTS fee_batch;
DROP TYPE IF EXISTS fee_batch_status;
-- +goose StatementEnd
60 changes: 16 additions & 44 deletions storage/postgres/schema/schema.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@

CREATE TYPE "fee_batch_status" AS ENUM (
'draft',
'sent',
'completed',
'failed'
);

CREATE TYPE "plugin_id" AS ENUM (
'vultisig-dca-0000',
'vultisig-payroll-0000',
'vultisig-fees-feee',
'vultisig-copytrader-0000'
Expand Down Expand Up @@ -59,36 +67,17 @@ BEGIN
END;
$$;

CREATE TABLE "fee" (
"id" "uuid" NOT NULL,
"fee_run_id" "uuid" NOT NULL,
"amount" integer NOT NULL,
"created_at" timestamp without time zone DEFAULT "now"()
);

CREATE TABLE "fee_run" (
CREATE TABLE "fee_batch" (
"id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
"status" character varying(50) DEFAULT 'draft'::character varying NOT NULL,
"batch_id" "uuid" NOT NULL,
"public_key" character varying(66) NOT NULL,
"status" "fee_batch_status" DEFAULT 'draft'::"public"."fee_batch_status" NOT NULL,
"amount" bigint NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"(),
"tx_hash" character varying(66),
"policy_id" "uuid" NOT NULL,
CONSTRAINT "fee_run_status_check" CHECK ((("status")::"text" = ANY ((ARRAY['draft'::character varying, 'sent'::character varying, 'completed'::character varying, 'failed'::character varying])::"text"[])))
"tx_hash" character varying(66)
);

CREATE VIEW "fee_run_with_totals" AS
SELECT "fr"."id",
"fr"."status",
"fr"."created_at",
"fr"."updated_at",
"fr"."tx_hash",
"fr"."policy_id",
COALESCE("sum"("fi"."amount"), (0)::bigint) AS "total_amount",
"count"("fi"."id") AS "fee_count"
FROM ("fee_run" "fr"
LEFT JOIN "fee" "fi" ON (("fr"."id" = "fi"."fee_run_id")))
GROUP BY "fr"."id", "fr"."status", "fr"."created_at", "fr"."updated_at", "fr"."tx_hash", "fr"."policy_id";

CREATE TABLE "plugin_policies" (
"id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
"public_key" "text" NOT NULL,
Expand Down Expand Up @@ -126,11 +115,8 @@ CREATE TABLE "tx_indexer" (
"updated_at" timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL
);

ALTER TABLE ONLY "fee"
ADD CONSTRAINT "fee_pkey" PRIMARY KEY ("id");

ALTER TABLE ONLY "fee_run"
ADD CONSTRAINT "fee_run_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "fee_batch"
ADD CONSTRAINT "fee_batch_pkey" PRIMARY KEY ("id");

ALTER TABLE ONLY "plugin_policies"
ADD CONSTRAINT "plugin_policies_pkey" PRIMARY KEY ("id");
Expand All @@ -141,12 +127,6 @@ ALTER TABLE ONLY "scheduler"
ALTER TABLE ONLY "tx_indexer"
ADD CONSTRAINT "tx_indexer_pkey" PRIMARY KEY ("id");

CREATE INDEX "idx_fee_id_fee_run_id" ON "fee" USING "btree" ("fee_run_id");

CREATE INDEX "idx_fee_run_created_at" ON "fee_run" USING "btree" ("created_at");

CREATE INDEX "idx_fee_run_status" ON "fee_run" USING "btree" ("status");

CREATE INDEX "idx_plugin_policies_active" ON "plugin_policies" USING "btree" ("active");

CREATE INDEX "idx_plugin_policies_plugin_id" ON "plugin_policies" USING "btree" ("plugin_id");
Expand All @@ -165,11 +145,3 @@ CREATE TRIGGER "trg_prevent_update_if_policy_deleted" BEFORE UPDATE ON "plugin_p

CREATE TRIGGER "trg_set_policy_inactive_on_delete" BEFORE INSERT OR UPDATE ON "plugin_policies" FOR EACH ROW WHEN (("new"."deleted" = true)) EXECUTE FUNCTION "public"."set_policy_inactive_on_delete"();

CREATE TRIGGER "update_fee_run_updated_at" BEFORE UPDATE ON "fee_run" FOR EACH ROW EXECUTE FUNCTION "public"."update_updated_at_column"();

ALTER TABLE ONLY "fee"
ADD CONSTRAINT "fee_fee_run_id_fkey" FOREIGN KEY ("fee_run_id") REFERENCES "fee_run"("id") ON DELETE CASCADE;

ALTER TABLE ONLY "fee_run"
ADD CONSTRAINT "fee_run_policy_id_fkey" FOREIGN KEY ("policy_id") REFERENCES "plugin_policies"("id") ON DELETE CASCADE;