@@ -147,6 +147,87 @@ CREATE POLICY token_metadata_erc721_delete ON ethereum."token_metadata_erc721"
147147FOR DELETE TO anon, authenticated, service_role
148148USING (true);
149149
150+ -- Table: ethereum.token_metadata_erc1155
151+
152+ -- DROP TABLE IF EXISTS ethereum.token_metadata_erc1155;
153+
154+ CREATE TABLE IF NOT EXISTS ethereum .token_metadata_erc1155
155+ (
156+ address text COLLATE pg_catalog." default" NOT NULL ,
157+ name text COLLATE pg_catalog." default" ,
158+ symbol text COLLATE pg_catalog." default" ,
159+ created_at timestamp with time zone NOT NULL DEFAULT now(),
160+ CONSTRAINT token_metadata_erc1155_pkey PRIMARY KEY (address),
161+ CONSTRAINT token_metadata_erc1155_address_key UNIQUE (address)
162+ );
163+
164+ ALTER TABLE IF EXISTS ethereum .token_metadata_erc1155
165+ OWNER to postgres;
166+
167+ ALTER TABLE ethereum .token_metadata_erc1155
168+ ENABLE ROW LEVEL SECURITY;
169+
170+ CREATE POLICY token_metadata_erc1155_select ON ethereum .token_metadata_erc1155
171+ FOR SELECT TO anon, authenticated, service_role
172+ USING (true);
173+
174+ CREATE POLICY token_metadata_erc1155_insert ON ethereum .token_metadata_erc1155
175+ FOR INSERT TO anon, authenticated, service_role
176+ WITH CHECK (true);
177+
178+ CREATE POLICY token_metadata_erc1155_update ON ethereum .token_metadata_erc1155
179+ FOR UPDATE TO anon, authenticated, service_role
180+ USING (true)
181+ WITH CHECK (true);
182+
183+ CREATE POLICY token_metadata_erc1155_delete ON ethereum .token_metadata_erc1155
184+ FOR DELETE TO anon, authenticated, service_role
185+ USING (true);
186+
187+ -- Table: ethereum.token_erc1155
188+
189+ -- DROP TABLE IF EXISTS ethereum.token_erc1155;
190+
191+ CREATE TABLE IF NOT EXISTS ethereum .token_erc1155
192+ (
193+ id uuid DEFAULT uuid_generate_v4() NOT NULL ,
194+ account_address text COLLATE pg_catalog." default" NOT NULL ,
195+ token_address text COLLATE pg_catalog." default" NOT NULL ,
196+ token_id numeric NOT NULL ,
197+ balance numeric NOT NULL DEFAULT 0 ,
198+ uri text COLLATE pg_catalog." default" ,
199+ last_balance_change timestamp without time zone NOT NULL DEFAULT now(),
200+ CONSTRAINT token_erc1155_pkey PRIMARY KEY (id),
201+ CONSTRAINT token_erc1155_contract_token_account_unique UNIQUE (token_address, token_id, account_address),
202+ CONSTRAINT token_erc1155_token_address_fkey FOREIGN KEY (token_address)
203+ REFERENCES ethereum .token_metadata_erc1155 (address) MATCH SIMPLE
204+ ON UPDATE NO ACTION
205+ ON DELETE NO ACTION
206+ );
207+
208+ ALTER TABLE IF EXISTS ethereum .token_erc1155
209+ OWNER to postgres;
210+
211+ ALTER TABLE ethereum .token_erc1155
212+ ENABLE ROW LEVEL SECURITY;
213+
214+ CREATE POLICY token_erc1155_select ON ethereum .token_erc1155
215+ FOR SELECT TO anon, authenticated, service_role
216+ USING (true);
217+
218+ CREATE POLICY token_erc1155_insert ON ethereum .token_erc1155
219+ FOR INSERT TO anon, authenticated, service_role
220+ WITH CHECK (true);
221+
222+ CREATE POLICY token_erc1155_update ON ethereum .token_erc1155
223+ FOR UPDATE TO anon, authenticated, service_role
224+ USING (true)
225+ WITH CHECK (true);
226+
227+ CREATE POLICY token_erc1155_delete ON ethereum .token_erc1155
228+ FOR DELETE TO anon, authenticated, service_role
229+ USING (true);
230+
150231-- Table: ethereum.token_erc721
151232
152233-- DROP TABLE IF EXISTS ethereum.token_erc721;
@@ -277,8 +358,15 @@ CREATE POLICY token_transfer_delete ON ethereum.token_transfer
277358FOR DELETE TO anon, authenticated, service_role
278359USING (true);
279360
361+ -- Adding token_id column to token_transfer for ERC-1155 support
362+ ALTER TABLE ethereum .token_transfer
363+ ADD COLUMN IF NOT EXISTS token_id numeric ;
364+
280365COMMENT ON COLUMN ethereum .token_transfer .value
281- IS ' ERC20 - token quantity, ERC721 - token ID' ;
366+ IS ' ERC20 - token quantity, ERC721 - not used (see token_id), ERC1155 - token quantity' ;
367+
368+ COMMENT ON COLUMN ethereum .token_transfer .token_id
369+ IS ' ERC721 - token ID, ERC1155 - token ID, ERC20 - not used' ;
282370
283371-- --------------------------------------------------------------------------------------------------
284372-- VIEWS
@@ -329,6 +417,31 @@ WITH (security_invoker = on)
329417ALTER TABLE ethereum .erc721_token_history_view
330418 OWNER TO postgres;
331419
420+ -- View: ethereum.erc1155_token_history_view
421+
422+ -- DROP VIEW IF EXISTS ethereum.erc1155_token_history_view;
423+
424+ CREATE OR REPLACE VIEW ethereum .erc1155_token_history_view
425+ WITH (security_invoker = on )
426+ AS
427+ SELECT
428+ tx .hash AS transaction_hash,
429+ tx." to" AS token_address,
430+ b .created_at ,
431+ tt .sender ,
432+ tt .recipient ,
433+ tt .token_id ,
434+ tt .value AS quantity
435+ FROM ethereum .transaction tx
436+ JOIN ethereum .block b ON tx .block_number = b .number
437+ JOIN ethereum .token_transfer tt ON tx .id = tt .transaction_id
438+ JOIN ethereum .token_metadata_erc1155 tkn ON tx." to" = tkn .address
439+ WHERE tt .token_id IS NOT NULL -- Ensure token_id is present (ERC-1155 or ERC-721)
440+ ORDER BY b .created_at , tt .recipient ;
441+
442+ ALTER TABLE ethereum .erc1155_token_history_view
443+ OWNER TO postgres;
444+
332445-- View: ethereum.token_erc20
333446
334447-- DROP MATERIALIZED VIEW IF EXISTS ethereum.token_erc20;
@@ -460,6 +573,104 @@ ALTER PROCEDURE ethereum.update_issued_erc721_tokens(numeric)
460573
461574GRANT EXECUTE ON PROCEDURE ethereum .update_issued_erc721_tokens (numeric ) TO public;
462575
576+ -- PROCEDURE: ethereum.update_issued_erc1155_tokens(numeric)
577+
578+ -- DROP PROCEDURE IF EXISTS ethereum.update_issued_erc1155_tokens(numeric);
579+
580+ CREATE OR REPLACE PROCEDURE ethereum .update_issued_erc1155_tokens (IN from_block_number numeric )
581+ LANGUAGE ' plpgsql'
582+ SET search_path = ethereum, public
583+ AS $BODY$
584+ DECLARE
585+ current_token_entry ethereum .token_erc1155 %ROWTYPE;
586+ token_transfer record;
587+ block_created_at timestamp ;
588+ BEGIN
589+ -- Get the block's creation time
590+ SELECT created_at
591+ FROM ethereum .block
592+ WHERE number = from_block_number
593+ INTO block_created_at;
594+
595+ IF NOT found THEN
596+ raise exception ' invalid block provided: %' , from_block_number
597+ USING hint = ' ensure that given block was synchronized correctly' ;
598+ END IF;
599+
600+ -- Process each transfer (distinct by token_address, token_id, recipient to handle batch transfers)
601+ FOR token_transfer IN SELECT
602+ *
603+ FROM ethereum .erc1155_token_history_view
604+ WHERE created_at >= block_created_at
605+ ORDER BY token_address, token_id, sender, recipient, created_at DESC
606+ LOOP
607+ -- Process sender (decrease balance)
608+ IF token_transfer .sender != ' 0x0000000000000000000000000000000000000000' THEN -- Not a mint
609+ SELECT * FROM ethereum .token_erc1155
610+ WHERE token_id = token_transfer .token_id
611+ AND token_address = token_transfer .token_address
612+ AND account_address = token_transfer .sender
613+ INTO current_token_entry;
614+
615+ IF found THEN
616+ -- Decrease sender's balance
617+ UPDATE ethereum .token_erc1155
618+ SET balance = GREATEST(0 , balance - token_transfer .quantity ),
619+ last_balance_change = token_transfer .created_at
620+ WHERE id = current_token_entry .id ;
621+
622+ -- Remove entry if balance reaches 0
623+ DELETE FROM ethereum .token_erc1155
624+ WHERE id = current_token_entry .id AND balance = 0 ;
625+ END IF;
626+ END IF;
627+
628+ -- Process recipient (increase balance)
629+ IF token_transfer .recipient != ' 0x0000000000000000000000000000000000000000' THEN -- Not a burn
630+ SELECT * FROM ethereum .token_erc1155
631+ WHERE token_id = token_transfer .token_id
632+ AND token_address = token_transfer .token_address
633+ AND account_address = token_transfer .recipient
634+ INTO current_token_entry;
635+
636+ IF NOT found THEN
637+ -- Create new entry for recipient
638+ raise notice ' create entry for token ID % on contract % for account %' ,
639+ token_transfer .token_id , token_transfer .token_address , token_transfer .recipient ;
640+ INSERT INTO ethereum .token_erc1155
641+ VALUES (
642+ uuid_generate_v4(),
643+ token_transfer .recipient ,
644+ token_transfer .token_address ,
645+ token_transfer .token_id ,
646+ token_transfer .quantity ,
647+ NULL , -- uri (can be fetched later)
648+ token_transfer .created_at
649+ );
650+ ELSE
651+ -- Increase recipient's balance
652+ IF current_token_entry .last_balance_change < token_transfer .created_at THEN
653+ raise notice ' update balance for token ID % on contract % for account %' ,
654+ token_transfer .token_id , token_transfer .token_address , token_transfer .recipient ;
655+ UPDATE ethereum .token_erc1155
656+ SET balance = balance + token_transfer .quantity ,
657+ last_balance_change = token_transfer .created_at
658+ WHERE id = current_token_entry .id ;
659+ ELSE
660+ raise notice ' current entry is more recent - ignore token ID % on contract % for account %' ,
661+ token_transfer .token_id , token_transfer .token_address , token_transfer .recipient ;
662+ END IF;
663+ END IF;
664+ END IF;
665+ END LOOP;
666+ END
667+ $BODY$;
668+
669+ ALTER PROCEDURE ethereum .update_issued_erc1155_tokens (numeric )
670+ OWNER TO postgres;
671+
672+ GRANT EXECUTE ON PROCEDURE ethereum .update_issued_erc1155_tokens (numeric ) TO public;
673+
463674-- FUNCTION: ethereum.get_missing_blocks_in_range(integer, integer)
464675
465676-- DROP FUNCTION IF EXISTS ethereum.get_missing_blocks_in_range(integer, integer);
0 commit comments